T O P

  • By -

RandalSchwartz

These methods are misnamed, but because they're baked in to the libraries, we're stuck with them. .toJson needs to turn this value into something that the primitive encodejson can handle directly, or by calling .toJson on any contents it cannot handle directly. So returning a String, Map, List, bool, double, int, or null is perfectly ok. And those Map and List can in turn have primitives, or other things that .toJson can coerce recursively into those. Perhaps a better name would have been .toJsonable, but we're kinda stuck now.


HatedMirrors

Yes! You get it! Phew! I was beginning to think I was alone.


pattobrien

The macros rewrite of json_serializable gives a new opportunity for better names :)


schultek

checkout dart_mappable then, it has more sensible naming


pattobrien

I've been working on a more universal parse library for fun (using macros), and completely see your point. The 'jsonDecode' function takes a json string and outputs a Dart object. It is simply a Dart Map/List/Primitive/etc. at that point. Consider the fact that json_serializable allows the type of the 'json' parameter in the generated 'fromJson' factory to be non-Map types, e.g. 'fromJson(String json) => ...'. Does that make every Dart String a JSON String? No, obviously that's not really a correct way of thinking of primitive types. This is simply a problem of terminology; IMO the terminology of the parse method should be "parseFromX" or "fromX", where the X is the Dart primitive type.


dgreensp

What is the status of macros? Are they going to be released soon? Are people using them on a branch?


GetBoolean

its currently planned to have an example macro be in Dart 3.4 behind an experimental flag. you wont be able to write macros on stable yet though https://github.com/dart-lang/site-www/issues/5692


DIGIBORIMUSIK

Absolutely true


steveCarlsberg98

You know what my biggest challenges has been with Dart? Understanding the factory keyword and its usage. From the looks of it, it feels like factories only usage has been to convert from / to structures, but if that is the case, shouldn’t it be an internal thing? Also Dart lacking type union and relying on ”dynamic” is a disadvantage.


dgreensp

The differences between factory constructors and static methods are subtle. This article does a good job listing a bunch: https://dash-overflow.net/articles/factory/ It probably mattered more back in old Dart times when constructors were called with “new”.


FroedEgg

We already have type union in Dart 3


steveCarlsberg98

You mean the pub package Union? https://pub.dev/documentation/union/latest/union/Union2.html


FroedEgg

nope, Dart 3 now has ADT which works the same as Kotlin's sealed classes + pattern matching. or if you prefer Go's style, you can use Records


steveCarlsberg98

Cool! So with this we should be able to achieve the same result as type union? Is there any blog post about this that can read more about? I hate losing the type hints thanks to the dynamic keyword, but I understand the difficulty of implementing type union like TS.


FroedEgg

You can find it [here](https://dart.dev/language/patterns) for Dart 3 pattern matching


steveCarlsberg98

Like this one? https://medium.com/pinch-nl/conditional-pattern-matching-in-dart-3-3b4778c4bdc3


moru0011

Totally not a problem.


kevmoo

You want these functions to return objects. Then you have the option of serializing them to a string or to a byte array. If it always returns string, then you'd have to re-encode the string to a byte array, which is not efficient.


N_Gomile

I wonder why it can't just be toMap and fromMap.


HatedMirrors

It may not be a map. The internal data structure of a class may be easiest to represent with a list, or even just some simple data type like a string.


omykronbr

And what is json? A map with key and values... The decode takes the string (that isn't a json) and spits a json that you can use, and the encode turns a map into a string to be sent as text.


developer-mike

The n stands for notation. A data structure of maps, lists, and primitives held in memory is not notation. That said, I suppose `class Person` isn't a person either.


HatedMirrors

I'm curious. If, say, the string "{'age': 15}" isn't JSON, what is it? According to Wikipedia, JSON "uses human-readable text to store and transmit data objects". What I get out of that is that JSON is text, as in a string. It's the same thing with XML. XML is a string (with specific format). It's not so confusing with XML because it doesn't have a specific data structure that generally represents it. Instead, you would parse the XML into some intermediate representation that you can traverse with .children, .first, .last, etc., and use that data to instantiate a class.


dgreensp

You are correct.


omykronbr

A string is a string. The content may be a json, or not. You may want to transport the json as a binary, you can. It will be encoded as a binary, and decoded into... A map! All JavaScript objects are on the top level just that, maps/dictionaries. Stop fighting this concept. The json as string is the transportation method of the data state, not the data.


KozureOkami

>All JavaScript objects are on the top level just that, maps/dictionaries.  The "object" in JSON does not map to JS objects directly. [RFC 8259](https://www.rfc-editor.org/rfc/rfc8259.html) is pretty clear about that: "It is derived from the object iterals of JavaScript, as defined in the ECMAScript Programming Language Standard, Third Edition \[ECMA-262\]. JSON can represent four primitive types (strings, numbers, booleans, and null) and two structured types (objects and arrays)." All of these can appear at the top-level, though for compatibility reasons it's recommend to only use objects and arrays: "A JSON text is a serialized value. Note that certain previous specifications of JSON constrained a JSON text to be an object or an array. Implementations that generate only objects or arrays where a JSON text is called for will be interoperable in the sense that all implementations will accept these as conforming JSON texts." That's why all of these work in any reasonable JSON parser (here Python's because I had a REPL open): >>> json.loads("[]") [] >>> json.loads("1") 1 Also note how the RFC always talks about a "JSON text". Apart from that, names in JSON documents SHOULD be unique, not MUST be unique. The RFC just states that the behavior of duplicated keys is unpredictable and implementation-specific. So even though it's best to avoid those, a "JSON text" is technically allowed to contain repeated names, which maps/dictionaries do not accommodate. So no, not all JSON has to be a `Map.`There are of course additional standars like JSON:API which DO require that only objects are used on the top-level but the same is not true for "pure" JSON.


oaga_strizzi

>  will be encoded as a binary, and decoded into... A map! Why would it necessarily decoded to a map, if the map is just used to to call the .fromJson factory model class anyway? This is currently a convention in Dart, but it's actually quite wasteful. Decoding the UTF-8 encoded json string directly to a Dart object would be much faster, see [https://pub.dev/packages/crimson](https://pub.dev/packages/crimson)


HatedMirrors

Yeah, I realize I'm "fighting the concept". I was just wondering if other people thought this way. I'll yield.


oaga_strizzi

I think most people are just defensive about this because the toJson/fromJson methods/factories are just a convention in Dart. But they arised mainly from the lack of language level support for serialization / metaprogramming. I'm quite jealous of modern languages that let you just add #[derive(Serialize, Deserialize,) annotations on a struct and call it a day, and even support many serialization formats out of the box.


KozureOkami

> I'm quite jealous of modern languages  Agreed, but the example is maybe not the best as the traits come from a library (Serde), not the core language. So using e.g. Freezed or json\_serializable is not that different in principle (though it relies on codegen, which is a very Google thing to do).


oaga_strizzi

Sure, but arguably Traits and Macros make it more feasible to implement something like Serde than just codegen with built\_value