hiranthaR / Json-to-Dart-Model

Json to Dart Model extension can convert JSON objects into Dart data classes. It supports pure Dart class conversion, Flutter-recommended JSON serialization using annotations, Freezed support, Effective Dart:Style, and many more features. Currently, it has more than 135,000 installs.
https://marketplace.visualstudio.com/items?itemName=hirantha.json-to-dart
MIT License
93 stars 17 forks source link

The toJson method does not properly transform List<T> type parameters #30

Closed heronlyj closed 3 years ago

heronlyj commented 3 years ago

The data type is the following

part of models.jsonc file:

[
    .........
    {
        "__className": "Course", // <- The base class name of the object.
        "type": 0,
        "name": "class name",
        "img": "image url",
        "id": 0,
        "courseNode": [
            {
                "type": 0,
                "level": 0,
                "sublevel": 0
            }
        ]
    }
]

Then the generated dart file looks like this (the toJson part)

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'course.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

_$_Course _$_$_CourseFromJson(Map<String, dynamic> json) {
  return _$_Course(
    type: json['type'] as int,
    name: json['name'] as String,
    img: json['img'],
    id: json['id'] as int,
    courseNode: (json['courseNode'] as List<dynamic>)
        .map((e) => CourseNode.fromJson(e as Map<String, dynamic>))
        .toList(),
  );
}

Map<String, dynamic> _$_$_CourseToJson(_$_Course instance) => <String, dynamic>{
      'type': instance.type,
      'name': instance.name,
      'img': instance.img,
      'id': instance.id,
      'courseNode': instance.courseNode,
    };

But the correct toJson code should look like this

Map<String, dynamic> _$_$_CourseToJson(_$_Course instance) => <String, dynamic>{
      'type': instance.type,
      'name': instance.name,
      'img': instance.img,
      'id': instance.id,
      'courseNode': instance.courseNode.map((e) => e.toJson()).toList(),
    };

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.0.3, on macOS 11.2.3 20D91 darwin-x64, locale en-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.55.2)
[✓] Connected device (2 available)

• No issues found!
  freezed_annotation: ^0.14.1
  json_annotation: ^4.0.1

dev_dependencies:
  flutter_test:
    sdk: flutter

  build_runner: ^1.12.2
  freezed: ^0.14.1+2
  json_serializable: ^4.1.0

vscode extension version: v3.1.1

iamarnas commented 3 years ago

@heronlyj Hi. Thank you for your report. I see you use json_serializable and I wonder have you same issues without json_serializable?

heronlyj commented 3 years ago

@iamarnas Hi.

If json_serializable is not referenced, thexxx.g.dart file will not be generated 😅

@heronlyj Hi. Thank you for your report. I see you use json_serializable and I wonder have you same issues without json_serializable?

heronlyj commented 3 years ago

@iamarnas Hi.

If don't use freezed, the result is the same, I mentioned the same issuse in

https://github.com/dart-lang/build/issues/3095

iamarnas commented 3 years ago

@heronlyj Hi.

If json_serializable is not referenced, the xxx.g.dart file will not be generated 😅

I meant that Json Serializable is false in your models.jsonc

Ok. Your generated JSON with Json to Dart Model looks as expected.

class Course {
  int type;
  String name;
  String img;
  int id;
  List<CourseNode> courseNode;

  Course({
    this.type,
    this.name,
    this.img,
    this.id,
    this.courseNode,
  });

  factory Course.fromJson(Map<String, dynamic> json) {
    return Course(
      type: json['type'] as int,
      name: json['name'] as String,
      img: json['img'] as String,
      id: json['id'] as int,
      courseNode: (json['courseNode'] as List<dynamic>)
          ?.map((e) => e == null
              ? null
              : CourseNode.fromJson(e as Map<String, dynamic>))
          ?.toList(),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'type': type,
      'name': name,
      'img': img,
      'id': id,
      'courseNode': courseNode?.map((e) => e?.toJson())?.toList(),
    };
  }
}

When you use Freezed or Json Serializable then Json to Dart Model generates only types and everything that happens after Json Serializable takes care of the rest and is responsible for generated code. Even Freezed depends on Json Serializable. If Json Serializable fails then the Freezed fails too. So that in that case Json to Dart Model more accurate than Json Serializable :sunglasses: and I can do nothing here need wait for a fix from the Json Serializable developers and no reason to keep these issues opened.

iamarnas commented 3 years ago

But thanks to you @heronlyj I found where I missed syntax correction :smiley: From now on, generated code will be cleaner.

iamarnas commented 3 years ago

I'm closing this because issue are with json_serializable.