JSON Parsing

devkwon·2023년 2월 5일
0

dart:convert

외부 종속성이나 특정 설정 프로세스가 없으며 빠른 컨셉 증명에 적합하다.
하지만 디코딩 논리를 다루는 것은 어렵기 때문에 프로젝트의 크기가 커질수록 오류가 발생하기 쉬워진다.

Decoding , Encoding JSON

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;
  }
}

Code generation

코드 생성을 통한 JSON 직렬화는 외부 라이브러리에서 인코딩 상용구(boilerplate)를 생성하는 것을 의미한다. json_serializable, built_value 등이 있다.

위 방식은 초기 설정을 제외하고 상용구가 필요하지 않으며 JSON 필드에 액세스할 때 오타가 날 경우 컴파일 타임에 포착이 된다.

중형 또는 대규모 프로젝트에 적합한 방식이다.

json_serializable

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 직렬화를 사용할 필요가 없어진다.

0개의 댓글