Mapping JSON into Class Objects

Viewed 16983

I am trying to map my JSON file into a class object, and then update the cards based on the newly received JSON.

My JSON structure is like this

 {
        "$class": "FirstCard",
        "id": "1",
        "description": "I am card number one",
        "Role": "attack",
        "score": 0,
        "tag": [
            "string"
        ],................}

my Class looks like this:

  class CardInfo {
  //Constructor
  String id;
  String description;
  String role;
  int score;

}

How can I map the values in my JSON file into the fields of objects created from CardInfo class?

Update

the following trial prints null at ci.description, does this mean the object was never created ?

const jsonCodec = const JsonCodec
_loadData() async {
  var url = 'myJsonURL';
  var httpClient  = createHttpClient();
  var response =await httpClient.get(url);
  print ("response" + response.body);
  Map cardInfo = jsonCodec.decode(response.body);
  var ci = new CardInfo.fromJson(cardInfo);
  print (ci.description); //prints null
}

Update2

Printing cardInfo gives the following:

{$class: FirstCard, id: 1, description: I am card number one,........}

Note that it resembles the original JSON but without the double quotes on string values.

6 Answers

I created some useful library for this using reflection called json_parser which is available at pub.

https://github.com/gi097/json_parser

You can add the following to your dependencies.yaml:

dependencies:
  json_parser: 0.1.1
  build_runner: 0.8.3

Then the json can be parsed using:

DataClass instance = JsonParser.parseJson<DataClass>(json);

Follow the README.md for more instructions.

The best solution I've found is this medium post

Which converts the Json to dart very easily

import 'package:json_annotation/json_annotation.dart';

part 'post_model.g.dart';

@JsonSerializable()
class PostModel {
  int userId;
  int id;
  String title;
  String body;
  PostModel(this.userId, this.id, this.title, this.body);
  factory PostModel.fromJson(Map<String, dynamic> json) => _$PostModelFromJson(json);
  Map<String, dynamic> toJson() => _$PostModelToJson(this);
}

this pkg can help you convert JSON to a class instance. https://www.npmjs.com/package/class-converter

import { property, toClass } from 'class-convert';

class UserModel {
  @property('i')
  id: number;

  @property()
  name: string;
}

const userRaw = {
  i: 1234,
  name: 'name',
};

// use toClass to convert plain object to class
const userModel = toClass(userRaw, UserModel);
// you will get a class, just like below one
{
  id: 1234,
  name: 'name',
}

You can generate them if you don't want to create them manually.

Add dependecies to pubspec.yaml:

dependencies:
  json_annotation: ^4.0.0
dev_dependencies:
  build_it: ^0.2.5
  json_serializable: ^4.0.2

Create configurtion file my_classes.yaml:

---
format:
  name: build_it
  generator:
    name: build_it:json
---

checkNullSafety: true

classes:
- name: CardInfo
  fields:
  - { name: id, type: String? }
  - { name: description, type: String? }
  - { name: role, type: String?, jsonKey: { name: Role } }
  - { name: score, type: int? }
  - { name: tag, type: List<String>, jsonKey: { defaultValue: [] } }

Run build process:

dart run build_runner build

Generated code my_classes.g.dart:

// GENERATED CODE - DO NOT MODIFY BY HAND

import 'package:json_annotation/json_annotation.dart';

part 'my_classes.g.g.dart';

// **************************************************************************
// build_it: build_it:json
// **************************************************************************

@JsonSerializable()
class CardInfo {
  CardInfo(
      {this.id, this.description, this.role, this.score, required this.tag});

  /// Creates an instance of 'CardInfo' from a JSON representation
  factory CardInfo.fromJson(Map<String, dynamic> json) =>
      _$CardInfoFromJson(json);

  String? id;

  String? description;

  @JsonKey(name: 'Role')
  String? role;

  int? score;

  @JsonKey(defaultValue: [])
  List<String> tag;

  /// Returns a JSON representation of the 'CardInfo' instance.
  Map<String, dynamic> toJson() => _$CardInfoToJson(this);
}

Now you can use them.

Related