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

Serialize/deserialize positional records as lists

Open Reprevise opened this issue 1 year ago • 2 comments

Appreciate the quick work on getting records implemented for json_serializable.

One request that I have is for records that only contain positional fields be serialized/deserialized as lists so that if I have this JSON list of doubles:

[0.34, 0.123, 0.542, 0.4143]

it would be deserialized into:

(0.34, 0.123, 0.542, 0.4143)

and vice versa.

Reprevise avatar May 17 '23 02:05 Reprevise

CC @jakemac53 who had similar reflections

kevmoo avatar May 17 '23 02:05 kevmoo

Fwiw my suggestion was to always use a list - and if there are named fields they would be serialized as a map, which would be the final entry in the list: (1, 2, {foo: 'bar'}) => [1, 2, {"foo": "bar"}]. I don't really like the idea of changing the entire strategy based on whether there are any named fields or not, so this avoids that.

jakemac53 avatar May 17 '23 14:05 jakemac53

@jakemac53 I like that idea in theory, how does it work with something like the following:

final (lat, long, :name) = (40.7128, 74.0060, name: "NY");

Would the named param order matter in the JSON list? For example, would this be parsed like the above?

[{"name": "NY"}, 40.7128, 74.0060]

Reprevise avatar May 17 '23 14:05 Reprevise

The named parameters would always have to be last in the list. The order they appear in the map doesn't matter though.

jakemac53 avatar May 17 '23 14:05 jakemac53

What about records that only contain named parameters? Would that be serialized as a list that only contains a map of the params? If that's the case, then I don't like that idea.

Reprevise avatar May 17 '23 14:05 Reprevise

What about records that only contain named parameters? Would that be serialized as a list that only contains a map of the params? If that's the case, then I don't like that idea.

Yes, it would be a list with only one item, a map. I like it more than the idea of changing the top level object used to represent a Record based on whether it has any or all named fields, but I agree it isn't totally ideal either.

TBH the current strategy also doesn't bother me so much, and it also is at least consistent.

jakemac53 avatar May 17 '23 15:05 jakemac53

The current serialization/deserialization for records only works for people who don't care what the JSON looks like and who have control over the JSON they parse. Everyone else will have to write their own converters.

Here is my desired serialization/deserialization:

Positional records

[40.7128, 74.0060]

Named param records

{"lat": 40.7128, "long": 74.0060}

Reprevise avatar May 17 '23 15:05 Reprevise

Yes, for any package which has its own bespoke serialization format, this package will not be able to parse it, you will have to provide your own custom implementation.

This package is generally intended to be used on both sides of serialization (backend and frontend), and if it isn't used in that way then you may have to do your own custom parsing, or mangle the data from the backend a bit to match the format that this package expects.

The current serialization/deserialization for records only works for people who don't care what the JSON looks like

While the current format is a bit weird, it is using the public getter names for all the values, so I would argue it is readable. It is weird because how you access positional fields on records is weird, but it is totally consistent with how records actually work.

jakemac53 avatar May 17 '23 15:05 jakemac53

so I would argue it is readable

Disagree with this, I think for positional records a list is much better and translates better as well. (and a map for only named records) It's just a question of changing the top-level item depending on the contents of the records which I understand you're against.

Perhaps we could make this behavior opt-in (which I suspect the vast majority of people would opt-in).

Reprevise avatar May 17 '23 16:05 Reprevise

This package is generally intended to be used on both sides of serialization (backend and frontend), and if it isn't used in that way then you may have to do your own custom parsing, or mangle the data from the backend a bit to match the format that this package expects.

JSON is meant to be language-independent and this package should try to minimize the amount of intervention required to map between the raw data and classes.

While the current format is a bit weird, it is using the public getter names for all the values, so I would argue it is readable. It is weird because how you access positional fields on records is weird, but it is totally consistent with how records actually work.

The getter names for positional records are purely an implementation detail in Dart that shouldn't exist in the JSON representation.

As there is no equivalent to a mixed record in JSON this should really be a concern for the developer - throwing an error during building doesn't seem unreasonable.

Ideally there would be an annotation parameter to choose whether to use an array or an object, defaulting IMO to positional=array, named(/mixed)=object.

nebkat avatar Jun 12 '23 16:06 nebkat