Skip to content

Conversation

@FrankenApps
Copy link
Contributor

This is an attempt to fix #1512.

As reported in this issue, the error

Null check operator used on a null value

occurs when trying to generate the code for a class inheriting from for example ListBase.

With this fix all tests including the newly introduced regression test for this issue succeed. However I am not very sure if this is the most elegant solution. It seems like the fields that triggered the error are later filtered out nevertheless, for which reason the offset should not matter in those cases.

@FrankenApps
Copy link
Contributor Author

The markdown linter failed due to rate limiting.

@kevmoo
Copy link
Collaborator

kevmoo commented Aug 4, 2025

Does this solve the problem for you? I don't see how the items in the list are actually serialized. Just the length...which is often not helpful.

@FrankenApps
Copy link
Contributor Author

Does this solve the problem for you? I don't see how the items in the list are actually serialized. Just the length...which is often not helpful.

The test case is rather synthetic and only constructed to showcase the bug.

Here is a more complete sample:

// Invoke build_runner using:
// dart run build_runner build --delete-conflicting-outputs

import 'dart:collection';

import 'package:json_annotation/json_annotation.dart';

part 'person_list.g.dart';

@JsonSerializable()
class Person {
  final PersonList myCustomList;

  Person(this.myCustomList);

  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);

  Map<String, dynamic> toJson() => _$PersonToJson(this);
}

@JsonSerializable()
class PersonList extends ListBase<String> {
  final List<String> _innerList = List.empty(growable: true);

  PersonList();

  @override
  int get length => _innerList.length;

  @override
  set length(int newLength) {
    _innerList.length = newLength;
  }

  @override
  String operator [](int index) => _innerList[index];

  @override
  void operator []=(int index, String value) {
    _innerList[index] = value;
  }

  @override
  void addAll(Iterable<String> iterable) {
    _innerList.addAll(iterable);
  }

  factory PersonList.fromJson(Map<String, dynamic> json) =>
      _$PersonListFromJson(json);

  Map<String, dynamic> toJson() => _$PersonListToJson(this);
}

The person_list.g.dart file now looks like this:

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'person_list.dart';

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

Person _$PersonFromJson(Map<String, dynamic> json) =>
    Person(PersonList.fromJson(json['myCustomList'] as Map<String, dynamic>));

Map<String, dynamic> _$PersonToJson(Person instance) => <String, dynamic>{
  'myCustomList': instance.myCustomList,
};

PersonList _$PersonListFromJson(Map<String, dynamic> json) => PersonList()
  ..first = json['first'] as String
  ..last = json['last'] as String
  ..length = (json['length'] as num).toInt();

Map<String, dynamic> _$PersonListToJson(PersonList instance) =>
    <String, dynamic>{
      'first': instance.first,
      'last': instance.last,
      'length': instance.length,
    };

Which is the same output as in version 6.9.5 and below.

If the model is now used like this:

import 'dart:convert';

import 'package:json_serialization_fail/person_list.dart';

void main(List<String> arguments) {
  final PersonList list = PersonList();
  list.addAll(["Person1", "Person2", "Person 3"]);
  final Person person = Person(list);

  print(json.encode(person.toJson()));
}

it successfully produces the following output just like in older versions of this package:

{"myCustomList":["Person1","Person2","Person 3"]}

@kevmoo kevmoo merged commit 7d8d510 into google:master Aug 4, 2025
17 of 18 checks passed
vkorencik pushed a commit to TypeSoft-Ltd/json_serializable.dart that referenced this pull request Sep 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] json_serializable cannot generate classes that inherit from LinkedListEntry

2 participants