google / google/json_serializable.dart

Handling empty nested json objects

Open
#1,370 0 comments 6 reactions 0 assignees View on GitHub
Dominant language
Dart
Stars
1.6k
Forks
461
Avg merge
45m
Merged PRs (30d)
1

Description

`flutter --version` output:
Flutter 3.10.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 796c8ef792 (5 months ago) • 2023-06-13 15:51:02 -0700
Engine • revision 45f6e00911
Tools • Dart 3.0.5 • DevTools 2.23.1

My issue is basically the same as #538 , but I am not satisfied with the reasoning for closing the issue.

Suppose I have two classes, a parent class:

```
import 'package:json_annotation/json_annotation.dart';
import 'package:playground/child_object.dart';

part 'parent_object.g.dart';

@JsonSerializable(explicitToJson: true)
class ParentObject {

@JsonKey(name: 'child')
final ChildObject? child;

ParentObject({this.child});

factory ParentObject.fromJson(Map json) => _$ParentObjectFromJson(json);

Map toJson() => _$ParentObjectToJson(this);
}

```
and a child class:

```
import 'package:json_annotation/json_annotation.dart';

part 'child_object.g.dart';

@JsonSerializable(explicitToJson: true)
class ChildObject {
@JsonKey(name: 'testString')
final String? testString;

ChildObject({this.testString});

factory ChildObject.fromJson(Map json) => _$ChildObjectFromJson(json);

Map toJson() => _$ChildObjectToJson(this);
}

```

If I try to convert

```
Map testJson = {
"child": {}
};
```
via `ParentObject.fromJson(testJson);` into my class I get the following exception:

> Unhandled exception:
> type '_Map' is not a subtype of type 'Map' in type cast
> #0 _$ParentObjectFromJson (package:playground/parent_object.g.dart:12:48)
> #1 new ParentObject.fromJson (package:playground/parent_object.dart:14:63)
> #2 main (package:playground/main.dart:4:31)
> #3 _delayEntrypointInvocation. (dart:isolate-patch/isolate_patch.dart:296:19)
> #4 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12)
>

because an empty `{}` is per default of type Map and the cast in the autogenerated file subsequently throws an exception
```

ParentObject _$ParentObjectFromJson(Map json) => ParentObject(
child: json['child'] == null
? null
: ChildObject.fromJson(json['child'] as Map),
);

```

Since my `testJson` is in a valid json format I do not think it is reasonable to expect the backend to change (which was the reasoning why issue #538 was closed).

If I change the autogenerated code and add an explicit cast

```
ParentObject _$ParentObjectFromJson(Map json) => ParentObject(
child: json['child'] == null
? null
: ChildObject.fromJson((json['child'] as Map).cast()),
);
```
it seems to work and my result is a ParentObject with an ChildObject, where the 'testString' field in the ChildObject is null.

Additionally one could add a `treatEmptyAsNull` property as suggested in #538

If I change the autogenerated code and add a check to see if the map is empty

```
ParentObject _$ParentObjectFromJson(Map json) => ParentObject(
child: json['child'] == null || (json['child'] as Map).isEmpty
? null
: ChildObject.fromJson((json['child'] as Map).cast()),
);

```

my result is a ParentObject where its ChildObject has value `null`

Are there any issues I don't recognize with the solutions I provide? Or is it possible to adapt the autogenerated code so that it can handle empty json objects

Thanks in advance

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.