RejectedSoftware Forums

Sign up

JSON undefined

JSON spec has no undefined, only null.

Why does there exist Json.undefined in vibe.data.json package?

Thanks.

Re: JSON undefined

As an addition to the question, I'd like to understand how Json.undefined is used.

Take a look at this example:

auto j = Json.emptyObject;
logInfo(to!string(j.test.type == Json.Type.undefined));
logInfo(to!string(j.test.type == Json.Type.Undefined));
logInfo(to!string(j.test is Json.undefined));
logInfo(to!string(j.test == Json.undefined));
j.test = Json.undefined;
logInfo(to!string(j.test is Json.undefined));
logInfo(to!string(j.test == Json.undefined));

The output is:

true

true

false

false

true

false

It seems odd that a non-existing field test in j is not undefined, and is not equal to undefined, though its type is equal to Json.Type.undefined.

Also can anyone explain why j.test is Json.undefined produces false, after explicit assignment: j.test = Json.undefined;?

Re: JSON undefined

Why does there exist Json.undefined in vibe.data.json package?

Possibly because null is a reserved keyword for D and can't be used as a custom object state.

It seems odd that a non-existing field test in j is not undefined, and is not equal to undefined, though its type is equal to Json.Type.undefined.

It should be specified in the docs, but I always use .to! on the Json object to verify its validity.

auto j = Json.emptyObject;assert(j.test.to!bool == false);assert(j.test.to!string == "undefined");

The reason being that comparing two Json objects with is will only compare the underlying pointers of two different pointers, it's a low-level feature of D that lets you "shoot yourself in the foot".

I agree though that j.test == Json.undefined should work as an exception, but I can't think of a way of making this happen because Json.undefined returns Json.init. The way opEquals is implented now for undefined is inspired by NaN from real, where two undefined variables can never be equal, as to avoid j.foo == j.bar returning true if they are undefined.

Re: JSON undefined

On Thu, 24 Jul 2014 13:54:12 GMT, Etienne Cimon wrote:

It should be specified in the docs, but I always use .to! on the Json object to verify its validity.

Be careful not to use .to!string on a string though, because it will add quotes " in that specific case. You must absolutely use .get!string on a string.

e.g.

auto j = Json.emptyObject;
if (someBool)
	j["test"] = "hello";
string test;
if (j.test.to!bool == true){ // not undefined, length > 0
	test = j.test.get!string;
	assert(test == "hello");
	test = j.test.to!string;
	assert(test == "\"hello\"");
}
else
	assert(test.to!string == "undefined");

Re: JSON undefined

Thanks Etienne Cimon.

Let me think about it thoroughly. Here're some questions to think about:

1) Why don't just use null instead of Json.undefined? What are implications of such an approach? Why Json.undefined was introduced?

2) get and to. It seems like the method of retrieving a value by its name with the default fallback value is missing, for example:

string name = obj.name.get!string("anonymous");

3) Just a note, I suppose the doc should advice to use:

obj["key"] notation in first place.

Think of working with JSON string: { "type": "employee", "name": "Mike" }. After parsing you will not be able to fetch "type" value using dot notation, as there is already type member sitting in any vibe.data.Json object.

4) Why do we need vibe.data.Json structure level at all?

Alternative to the Json structure is Variant[string]. For arrays one may use Variant[]. And provide some functions like "readJson", "writeJson", and maybe some other variations.

Re: JSON undefined

On Thu, 24 Jul 2014 14:30:08 GMT, Pavel wrote:

Thanks Etienne Cimon.

Let me think about it thoroughly. Here're some questions to think about:

1) Why don't just use null instead of Json.undefined? What are implications of such an approach? Why Json.undefined was introduced?

The null type is already reserved for pointers, and there's no way to overload operations on a null type with a Json object.

2) get and to. It seems like the method of retrieving a value by its name with the default fallback value is missing, for example:

string name = obj.name.get!string("anonymous");

True, that's why there's an opCast for this though so you can also do string name = obj.name to achieve the same result, but I prefer the more verbose way (personally).

3) Just a note, I suppose the doc should advice to use:

obj["key"] notation in first place.

Think of working with JSON string: { "type": "employee", "name": "Mike" }. After parsing you will not be able to fetch "type" value using dot notation, as there is already type member sitting in any vibe.data.Json object.
4) Why do we need vibe.data.Json structure level at all?

Alternative to the Json structure is Variant[string]. For arrays one may use Variant[]. And provide some functions like "readJson", "writeJson", and maybe some other variations.

I think it's true that there are flaws with having a .type property, which collides with opDispatch, the workaround is more likely going to be using opIndex by doing json["type"], although this is a very minor workaround compared to the level of verbosity that would be needed to make Variant[string] work with Json deserialized objects ... how would you check for a null type in a variant for example?

Re: JSON undefined

On Thu, 24 Jul 2014 14:30:08 GMT, Pavel wrote:

Thanks Etienne Cimon.

Let me think about it thoroughly. Here're some questions to think about:

1) Why don't just use null instead of Json.undefined? What are implications of such an approach? Why Json.undefined was introduced?

undefined is specifically there to be able to distinguish between a value that is null and a non-existent value. As such, undefined fields in JSON arrays are either omitted (in case of a dictionary), or replaced with null (in case of a linear array) when converting the Json struct to a JSON string.

2) get and to. It seems like the method of retrieving a value by its name with the default fallback value is missing, for example:

string name = obj.name.get!string("anonymous");

This would be obj.name.opt!string("anonymous"). The get name here is modeled after Variant.get and not after the get method of associative arrays.

3) Just a note, I suppose the doc should advice to use:

obj["key"] notation in first place.

Think of working with JSON string: { "type": "employee", "name": "Mike" }. After parsing you will not be able to fetch "type" value using dot notation, as there is already type member sitting in any vibe.data.Json object.

There is actually an open ticket that requests to remove Json.opDispatch altogether. Based on my personal view I'd agree, but I know that there are also some people who strongly favor the dot based syntax, so I'm reluctant to actually remove it.

4) Why do we need vibe.data.Json structure level at all?

Alternative to the Json structure is Variant[string]. For arrays one may use Variant[]. And provide some functions like "readJson", "writeJson", and maybe some other variations.

Because Variant is too lax in what it can take. The Json struct statically makes sure that only the supported types can be stored. It would be possible to use an Algebraic!(bool, int, float, ...) (not sure if it would accept typeof(null), though), but it's often also very useful to be able to refer to the contained types using an enum instead of a type info pointer, for example to be able to use final switch, or using the type as efficient AA keys or indices.

What I'm actually planning to do though, is to implement a generic FixedVariant type that basically is a fully generic tagged union. This can then be used as alias Json = FixedVariant!(JsonType, bool, int, ...) and has some advantages, such as supporting conversion to other similar FixedVariant types like the corresponding Bson definition.