외부 종속성이나 특정 설정 프로세스가 없으며 빠른 컨셉 증명에 적합하다.
하지만 디코딩 논리를 다루는 것은 어렵기 때문에 프로젝트의 크기가 커질수록 오류가 발생하기 쉬워진다.
jsonDecode()를 통해 JSON String을 Map으로 변환할 수 있고,
// NOTE: Be sure to use double quotes ("),
// not single quotes ('), inside the JSON string.
// This string is JSON, not Dart.
var jsonString = '''
[
{"score": 40},
{"score": 80}
]
''';
var scores = jsonDecode(jsonString);
assert(scores is List);
var firstScore = scores[0];
assert(firstScore is Map);
assert(firstScore['score'] == 40);
다음과 같이 jsonEncode()를 통해 Map을 JSON String으로 변환도 가능하다
var scores = [
{'score': 40},
{'score': 80},
{'score': 100, 'overtime': true, 'special_guest': null}
];
var jsonText = jsonEncode(scores);
assert(jsonText ==
'[{"score":40},{"score":80},'
'{"score":100,"overtime":true,'
'"special_guest":null}]');
class roomInfo {
String? roomID;
String? userID;
roomInfo({this.roomID, this.userID});
roomInfo.fromJson(Map<String, dynamic> json) {
roomID = json['roomID'];
userID = json['userID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['roomID'] = this.roomID;
data['userID'] = this.userID;
return data;
}
}
코드 생성을 통한 JSON 직렬화는 외부 라이브러리에서 인코딩 상용구(boilerplate)를 생성하는 것을 의미한다. json_serializable, built_value 등이 있다.
위 방식은 초기 설정을 제외하고 상용구가 필요하지 않으며 JSON 필드에 액세스할 때 오타가 날 경우 컴파일 타임에 포착이 된다.
중형 또는 대규모 프로젝트에 적합한 방식이다.
import 'package:json_annotation/json_annotation.dart';
/// This allows the `User` class to access private members in
/// the generated file. The value for this is *.g.dart, where
/// the star denotes the source file name.
part 'user.g.dart';
/// An annotation for the code generator to know that this class needs the
/// JSON serialization logic to be generated.
@JsonSerializable()
class User {
User(this.name, this.email);
String name;
String email;
/// A necessary factory constructor for creating a new User instance
/// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
/// The constructor is named after the source class, in this case, User.
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
/// `toJson` is the convention for a class to declare support for serialization
/// to JSON. The implementation simply calls the private, generated
/// helper method `_$UserToJson`.
Map<String, dynamic> toJson() => _$UserToJson(this);
}
// decode a JSON string the json_serializable way
Map<String, dynamic> userMap = jsonDecode(jsonString);
var user = User.fromJson(userMap);
part of 'example.dart';
Person _$PersonFromJson(Map<String, dynamic> json) => Person(
firstName: json['firstName'] as String,
lastName: json['lastName'] as String,
dateOfBirth: json['dateOfBirth'] == null
? null
: DateTime.parse(json['dateOfBirth'] as String),
);
Map<String, dynamic> _$PersonToJson(Person instance) => <String, dynamic>{
'firstName': instance.firstName,
'lastName': instance.lastName,
'dateOfBirth': instance.dateOfBirth?.toIso8601String(),
};
json_serializable을 사용하면 직렬화 논리가 포함된 파일이 생성되는데(user.g.dart) 이 파일로 라이브러리가 자동으로 직렬화를 책임져주기 때문에 수동 json 직렬화를 사용할 필요가 없어진다.