json_serializable.dart icon indicating copy to clipboard operation
json_serializable.dart copied to clipboard

Consider option to define `Codec<Map<String, dynamic>, MyType>`

Open jonasfj opened this issue 7 years ago • 5 comments

Might it not be nice to offer declaring a Codec to convert to/from JSON for MyType

import 'package:json_annotation/json_annotation.dart';

part 'example.g.dart';

@JsonCodec()
class Person {
  String name;
  @JsonKey(name: 'date-of-birth', nullable: false)
  DateTime dateOfBirth;
  ...
}

Then a generated file a long the lines of:

import 'dart:convert';

part of 'example.dart';

Codec<Person, Object> PersonJsonCodec = ...;

This way I could do:

var personCodec = PersonJsonCodec.fuse(JsonCode.fuse(Utf8Codec));

// Convert: bytes -> string -> json -> Person, in a single step
Person somePerson = personCodec.decode(List<int>.from(bytes));

Further more, other libraries that accepts the Codec or Converter interfaces would be able to use this.. I could imagine packages that accepts a Codec prior to creating an abstraction for read/write files, cache, database entries, making RPCs.

Notably, it would also free me from writing constructors...

jonasfj avatar Nov 22 '18 13:11 jonasfj

PRs welcome!

kevmoo avatar Nov 26 '18 17:11 kevmoo

I have added this, but it is not configureable yet. This was on the way of having a strategy to auto-decode specific subclasses by looking at a property on the containing class. There may be a Codec that understands this subclassing in some way, not sure yet.

I do not know how to handle imports in generated files yet (dart:convert is required for Codec and Converter).

Lastly I don't know if extending Codec is sufficient to enable to use .fuse.

https://github.com/denkuy/json_serializable/commit/883688d65ca8bfb0ad3885725ca5ebb99b9acabc

@kevmoo is this something you can use already?

ghost avatar Jan 05 '19 01:01 ghost

@denkuy, Can't we solve the import issue by adding the following to json_annotation.dart in package json_annotation.

export "dart:convert" show Converter, Codec

Users of this library always has to import package:json_annotation/json_annotation.dart to get the annotations. So it'll always be imported.

jonasfj avatar Jan 07 '19 09:01 jonasfj

Lastly I don't know if extending Codec is sufficient to enable to use .fuse.

It should be... afaik, you only have to override fuse if you want to provide a more efficient implementation. For example, if you fuse the JsonCodec and Utf8Codec codec the SDK will internally create a codec that uses JsonUtf8Encoder.

I suppose we could in some distant future make all of this faster by implementing could make a.fuse with an optimized code path for encoding/decoding JSON to/from utf8. It would certainly be faster and less memory intensive to use a SAX json parser instead of converting to an intermediate Map<String,dynamic> object.

But let's leave such optimizations for when there are users who need it.

jonasfj avatar Jan 07 '19 09:01 jonasfj

See also https://github.com/dart-lang/sdk/issues/35693

kevmoo avatar Jan 17 '19 21:01 kevmoo