source

모든 모델 클래스에 JSON 시리얼라이저를 추가하시겠습니까?

factcode 2023. 2. 13. 20:50
반응형

모든 모델 클래스에 JSON 시리얼라이저를 추가하시겠습니까?

Dart에서의 JSON 인코딩에 관한 한, Seth Ladd의 설명에 따르면 현재 최종적으로 승인된 공식 방법은 다음과 같습니다.dart:convert+JSON.Encode

예를 들어 다음과 같은 모델 클래스(PODO)가 많이 있다고 합시다.

class Customer
{
  int Id;
  String Name;
}

도메인 오브젝트를 다음과 같이 JSON 인코딩할 수 있으면 좋겠습니다.

var customer = new Customer()
  ..Id = 17
  ..Name = "John";
var json = JSON.encode(customer);

불행히도, 이건 효과가 없을 거야...

Uncaught Error: Converting object to an encodable object failed.
Stack Trace: 
#0      _JsonStringifier.stringifyValue (dart:convert/json.dart:416)
#1      _JsonStringifier.stringify (dart:convert/json.dart:336)
#2      JsonEncoder.convert (dart:convert/json.dart:177)
....

가 명시적으로 말하지 한...우리가 명시적으로 말하지 않는 한dart:convert다음 중 하나:

class Customer
{
  int Id;
  String Name;

  Map toJson() { 
    Map map = new Map();
    map["Id"] = Id;
    map["Name"] = Name;
    return map;
  }  
}

ㅇㅇㅇㅇㅇㅇㅇㅇㅇ를 요?toJson모든 모델 클래스에 적용하거나 더 나은 방법이 있을까요?

편집: 이것은 제가 찾고 있는 심플한 시리얼라이제이션입니다.

{
    "Id": 17,
    "Name": "John"
}

ToJsonServiceStack에 있습니다.를 들어 텍스트.

Dart의 시리얼라이제이션 라이브러리(아래 Matt B의 답변 참조)는 올바른 방향으로 나아가는 단계인 것 같습니다.하지만 이건...

var serialization = new Serialization()
  ..addRuleFor(Customer); 
var json = JSON.encode(serialization.write(customer, format: new SimpleJsonFormat()));

...는 다음 값(키 없음)을 가진 배열만 생성합니다.

[17,"John"]

한편 기본 SimpleMapFormat을 사용하면 이 복잡한 표현이 생성됩니다.

아직 내가 찾던 걸 못 찾았어...

편집 2: 일부 컨텍스트 추가:저는 Dart에서 RESTful 웹 서비스를 구축하고 있으며, 다른 Dart 클라이언트뿐만 아니라 어떤 클라이언트에서도 쉽게 사용할 수 있는 JSON 시리얼화를 찾고 있습니다.예를 들어 이 질문에 대해 스택 Exchange API를 쿼리하면 이 JSON 응답이 생성됩니다.이것이 제가 찾고 있는 시리얼라이제이션 형식입니다.-아니면 Twitter REST APIFacebook Graph API에서 반환되는 전형적인 JSON 응답을 보세요.

편집 3: 나는 이것에 대해 작은 블로그 투고를 썼다.해커 뉴스에 대한 설명도 참조하십시오.

IMO 이것은 Dart의 주요 결점이며, 웹 어플리케이션의 초점을 생각하면 놀라운 결과입니다.표준 라이브러리에서 JSON을 지원한다는 것은 JSON에서 또는 JSON에서 클래스를 시리얼화하는 것이 물처럼 기능한다는 것을 의미한다고 생각했지만 안타깝게도 JSON 지원은 불완전한 것 같습니다.이 경우 표준(PODO) 클래스를 구성하기 위해 느슨하게 타이핑된 맵을 사용하거나 불필요한 보일러 플레이트를 사용할 수 있습니다.예상대로 연재할 수 있습니다.

반사 및 미러 지원 없음

Flutter와 같은 인기 있는 Dart 플랫폼은 Reflection/Mirrors를 지원하지 않기 때문에 코드 생성 솔루션을 사용하는 방법밖에 없습니다.ServiceStack의 Dart 및 Flutter 기본 지원 방식을 사용하면 원격 URL에서 모든 ServiceStack 서비스에 대해 입력된 Dart 모델을 생성할 수 있습니다. 예:

$ npm install -g @servicestack/cli

$ dart-ref https://techstacks.io

에서 지원됩니다.NET Core 및 의 어느쪽인가?NET의 인기 있는 호스팅 옵션.

위의 예에서는 의 Typeed API를 생성합니다.techstacks.io/types/dart 엔드포인트에서 생성된 DTO를 사용하여 NET TechStacks 프로젝트를 수행합니다.그러면 Dart의 JsonCodec 패턴에 따른 모델이 생성됩니다.이 패턴에서는 Dart 모델의 시리얼화를 커스터마이즈 할 수 있습니다.fromJson 컨스트럭터 및 " " " " " "toJson()메서드에서는 .instance DTO의 예를 나타냅니다.

class UserInfo implements IConvertible
{
    String userName;
    String avatarUrl;
    int stacksCount;

    UserInfo({this.userName,this.avatarUrl,this.stacksCount});
    UserInfo.fromJson(Map<String, dynamic> json) { fromMap(json); }

    fromMap(Map<String, dynamic> json) {
        userName = json['userName'];
        avatarUrl = json['avatarUrl'];
        stacksCount = json['stacksCount'];
        return this;
    }

    Map<String, dynamic> toJson() => {
        'userName': userName,
        'avatarUrl': avatarUrl,
        'stacksCount': stacksCount
    };

    TypeContext context = _ctx;
}

이 모델에서는 Dart의 기본 제공 json:convert API를 사용하여 모델을 JSON으로 직렬화 및 역직렬화할 수 있습니다. 예:

//Serialization
var dto = new UserInfo(userName:"foo",avatarUrl:profileUrl,stacksCount:10);
String jsonString = json.encode(dto);

//Deserialization
Map<String,dynamic> jsonObj = json.decode(jsonString);
var fromJson = new UserInfo.fromJson(jsonObj);

이 접근법의 장점은 Dart 2의 Strong Mode 유무에 관계없이 Flutter 및 AngularDart 또는 Dart Web Apps를 포함한 모든 Dart 플랫폼에서 작동한다는 것입니다.

생성된 DTO를 Serviceestack의 Dart 패키지와 함께 사용하면 엔드 투 엔드 타입의 솔루션을 사용할 수 있습니다.이 솔루션에서는, 타입이 끝난 DTO와의 사이에 JSON 시리얼화를 처리할 수 있습니다.다음은 예를 제시하겠습니다.

var client = new JsonServiceClient("https://www.techstacks.io");
var response = await client.get(new GetUserInfo(userName:"mythz"));

자세한 내용은 ServiceStack의 네이티브 Dart 지원에 대한 문서를 참조하십시오.

거울 달린 다트

Mirrors 지원을 이용할 수 있는 플랫폼에서 Dart를 사용하는 경우 Mixin을 사용하는 데 가장 적은 노력이 필요하다는 것을 알게 되었습니다. 예를 들어 다음과 같습니다.

import 'dart:convert';
import 'dart:mirrors';

abstract class Serializable {

  Map toJson() { 
    Map map = new Map();
    InstanceMirror im = reflect(this);
    ClassMirror cm = im.type;
    var decls = cm.declarations.values.where((dm) => dm is VariableMirror);
    decls.forEach((dm) {
      var key = MirrorSystem.getName(dm.simpleName);
      var val = im.getField(dm.simpleName).reflectee;
      map[key] = val;
    });
    
    return map;
  }  

}

PODO 클래스와 함께 사용할 수 있는 기능:

class Customer extends Object with Serializable
{
  int Id;
  String Name;
}

같이 쓸 수요.JSON.encode:

var c = new Customer()..Id = 1..Name = "Foo";
  
print(JSON.encode(c));

결과:

{"Id":1,"Name":"Foo"}

주의: 미러 사용에 관한 주의사항을 참조하십시오.

맵이나 JSON으로 변환하는 등의 문제를 해결하기 위해 Exportable 라이브러리를 작성했습니다.이를 사용하면 모델 선언은 다음과 같습니다.

import 'package:exportable/exportable.dart';

class Customer extends Object with Exportable {
  @export int id;
  @export String name;
}

JSON으로 변환하려면 다음 작업을 수행합니다.

String jsonString = customer.toJson();

또한 JSON 문자열에서 새 개체를 쉽게 초기화할 수 있습니다.

Customer customer = new Customer()..initFromJson(jsonString);

또는 다음 중 하나:

Customer customer = new Exportable(Customer, jsonString);

상세한 것에 대하여는, README 를 참조해 주세요.

또는 Serialization 패키지를 사용하여 클래스에 규칙을 추가하는 방법도 있습니다.가장 기본적인 양식은 반사를 사용하여 속성을 자동으로 가져옵니다.

Redstone Mapper는 제가 사용한 것 중 최고의 연재 라이브러리입니다.JsonObject 및 Exportable에는 일부 클래스를 확장해야 하는 단점이 있습니다.Redstone Mapper를 사용하면 이런 구조를 만들 수 있습니다.

class News
{
    @Field() String title;
    @Field() String text;
    @Field() List<FileDb> images;
    @Field() String link; 
}

및 setters와 되므로 getters에 주석을 달지 않고 수 .@Field()필드 이름을 json에서 json으로 변경할 수 있습니다.네스트된 오브젝트가 있으면 서버와 클라이언트에서 동작합니다.Redstone Server MongoDB에 대해 설명하겠습니다.

내가 본 유일한 틀은 다트슨이지만 레드스톤 매퍼와 비교하면 아직 부족한 점이 있다.

해결 방법:

class Customer extends JsonObject
{
  int Id;
  String Name;
  Address Addr;
}

class Address extends JsonObject{
  String city;
  String State;
  String Street;
}

그러나 나의 목표는 모델 클래스에서 json으로 데이터를 바인드하는 것이다.이 솔루션은 모델 클래스를 수정할 수 있는 경우 작동하지만 반대로 모델 클래스를 변환하려면 솔루션 "외부"를 사용해야 합니다.

참고 항목: Dart에서 JsonObject 라이브러리를 사용한 JSON 목록 해석

이 문제를 해결하는 다른 패키지는 built_value입니다.

https://github.com/google/built_value.dart

built_value를 사용하면 모델 클래스는 다음과 같습니다.

abstract class Account implements Built<Account, AccountBuilder> {
  static Serializer<Account> get serializer => _$accountSerializer;

  int get id;
  String get name;
  BuiltMap<String, JsonObject> get keyValues;

  factory Account([updates(AccountBuilder b)]) = _$Account;
  Account._();
}

built_value는 단순히 시리얼라이제이션에 관한 것이 아니라 operator==, hashCode, toString 및 빌더 클래스도 제공합니다.

나는 이것으로 달성했습니다.

이 작업을 수행하려면 명시적으로 통과하십시오.ToJson: 클래스 선언 위의 @JsonSerialable() 주석에서 true입니다.User 클래스는 다음과 같이 표시됩니다.

import 'address.dart';
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';

@JsonSerializable(explicitToJson: true)
class User {
  String firstName;
  Address address;

  User(this.firstName, this.address);

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

https://flutter.dev/docs/development/data-and-backend/json#generating-code-for-nested-classes를 확인하십시오.

https://ashamp.github.io/jsonToDartModel/ 온라인 툴을 직접 사용하는 것을 선호합니다.

다음과 같은 기능이 있습니다.

  • 온라인 사용, 플러그인 없음
  • 지원 다차원 리스트
  • 복합 json 지원
  • support 모든 소품을 String type으로 변환
  • 빈 소품 경고
  • 1열 종렬
  • dart 키워드 보호
  • 인스턴트 컨버터

다른 도구보다 좋은 것 같아요.제안, 문제 또는 버그 보고가 있으시면 환영합니다.

일부 답변은 Flutter 2에 더 이상 적용되지 않습니다. 다음은 toJson 및 fromJson 메서드를 자동으로 생성하는 프로세스입니다.

https://syslog.dev/dev/development/data-and-syson/json#creating-model-the-json_creatible-way

PS: Asp에 있는 Newtonsoft 라이브러리를 사용하는 것처럼 간단했으면 합니다.이 솔루션은 자동화 솔루션에 가장 가깝습니다.

언급URL : https://stackoverflow.com/questions/20024298/add-json-serializer-to-every-model-class

반응형