dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.19k stars 1.56k forks source link

GoLang like json serialization built into Dart in stead of using built_value #36066

Open archanpaul opened 5 years ago

archanpaul commented 5 years ago

Cross posting from flutter-dev message.

I was watching the Episode 2 of "The boring Flutter development show" on data serialisation using built_value (thank you guys for putting together a good show and it's interesting to see you guys struggling with built_value and serialisation). I believe built_value though useful but unnecessarily complex (reminds me about bloated Java) compared to GoLang's approach to json serialisation where we just write (object) models (including complex and nested) and Marshal/Unmarshall to json without much thinking about meta programming! Considering that both Go and Dart coming from Google, Dart dev team should consider adapting GoLang's way of serialisation.

Archan

rrousselGit commented 5 years ago

It's not that Dart doesn't offer these. But they are not available in Flutter, because mirroring is disabled.

Go would face the same issue

You can use json_serializable which is easier than built_value as an alternative

archanpaul commented 5 years ago

Looks like json_serializable also need meta, annotation, code generation etc, though easier compared to built_value.

A sample Go code for json serialization is easy as following (no meta, no annotation).

type Message struct {
    Name string
    Body string
    Time int64
}
m := Message{"Alice", "Hello", 1294706395881547000}
b, err := json.Marshal(m)

b := []byte(`{"Name":"Bob","Food":"Pickle"}`)
var m Message
err := json.Unmarshal(b, &m)

I think Dart should have something silimar unless the language construct blocks the feature.

rrousselGit commented 5 years ago

As I said, Go would suffer from the same problem in Flutter. This use mirroring to work, which isn't enabled in Flutter

If you're using a web app, you can already use something similar to go:

https://www.dartlang.org/guides/libraries/library-tour#dartconvert---decoding-and-encoding-json-utf-8-and-more

sassman commented 5 years ago

In kotlin there is the concept of a data class that comes with certain capabilities. For dart I wish the whole serialize topic would not be that much of thing. I understand the that mirroring is not wanted for flutter for some reasons, but what if the language itself would offer that concept to allow no mirroring globally but for dedicated classes comes with the feature, in a way that serialization to json e.g. would be possible without the drawbacks that are there right now.

lrhn commented 5 years ago

Go does not allow unmarhalling of interfaces, you need to know the concrete type of the object being unmarshalled. That makes it much harder for Dart to do something similar because we use interfaces much more than Go does. Dart also uses first-class function values much more than Go, and those also cannot be serialized by Go's JSON marhsaller.

It's not impossible to introduce some kind of object marshalling primitive which serializes the internal state of an object, and then allows deserializing of that data again if you know the concrete types of everything, but I fear that that will only very rarely be the use-case in Dart. Any time you use an interface type (any type with more than one concrete subclass) or any function type, marshalling will have to fail, so effectively we are restricted to simple value types with no function valued fields.

davidmorgan commented 5 years ago

Actually built_value does support interface types :) ... as well as serialization/deserialization without knowing the types at all. (Provided all values belong to the set of types you've declared to be serializable).

The wire format changes depending on whether types are fully known statically; if they are not, the type is specified on the wire. Of course we have to generate enough metadata/factories to deserialize.

Conceptually it's fairly similar to Java's built in serialization, but the wire format is much more forgiving, and can map to formats used by other systems.

We can't do anything about function types, of course, but this hasn't been a problem in practice.

I'd definitely like to see more language support in this area, but it's a big topic. I imagine, if we do make progress, it will be via something like data classes.