July 24, 2014
On Thursday, 24 July 2014 at 15:34:22 UTC, Ali Çehreli wrote:
> On 07/24/2014 08:29 AM, Pavel wrote:
>
>> writeln(parsed["fail"] == null);
>>
>> Now compiler complains:
>>
>> Error: incompatible types for ((parsed.opIndex("fail")) == (null)):
>> 'JSONValue' and 'typeof(null)'
>>
>>
>> WAT?!
>
> Comparing against null should be done with the 'is' operator, not the == operator:
>
>     if (x is null)
>
> Ali

My compiler disagreed:

app.d(8): Error: incompatible types for ((parsed.opIndex("fail")) is (null)): 'JSONValue' and 'typeof(null)'
July 24, 2014
On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote:
> On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:
>> Ok, let me start with the sample code:
>>
>> import std.stdio;
>> import std.json;
>>
>> void main() {
>>  scope(failure) writeln("FaILED!!");
>>  string jsonStr = `{ "name": "1", "type": "r" }`;
>>  auto parsed = parseJSON(jsonStr);
>>  string s = parsed["fail"].str;
>>  writeln(s == "");
>>  writeln(s is null);
>>  writeln(s);
>> }
>>
>> Running "rdmd app.d" doesn't produce any output.
>> Can anyone explain such a behavior???
>>
>>
>> PS: Running dmd v2.065 on Linux x64.
>
> It's a bug in std.json (you should get a segfault, not no output at all)
>
> It is fixed now and I'm pretty sure it will be in 2.066
>
> std.json has been improved a lot, but I would still recommend using http://vibed.org/api/vibe.data.json/ instead

perhaps "bug" is too strong a word, but it was a deficiency that is now corrected. You will get an exception thrown now and everything should work how you expect.
July 24, 2014
On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote:
> On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:
>> Ok, let me start with the sample code:
>>
>> import std.stdio;
>> import std.json;
>>
>> void main() {
>>  scope(failure) writeln("FaILED!!");
>>  string jsonStr = `{ "name": "1", "type": "r" }`;
>>  auto parsed = parseJSON(jsonStr);
>>  string s = parsed["fail"].str;
>>  writeln(s == "");
>>  writeln(s is null);
>>  writeln(s);
>> }
>>
>> Running "rdmd app.d" doesn't produce any output.
>> Can anyone explain such a behavior???
>>
>>
>> PS: Running dmd v2.065 on Linux x64.
>
> It's a bug in std.json (you should get a segfault, not no output at all)
>
> It is fixed now and I'm pretty sure it will be in 2.066
>
> std.json has been improved a lot, but I would still recommend using http://vibed.org/api/vibe.data.json/ instead

I'm pretty sure it's improving, but it has that "Java" disease, which is creating new Types, which are just wrappers for common types.
Why don't just use Variant[string] for objects, and Variant[] for arrays. This way you won't be putting another layer of knowledge for those who work with std.json.
July 24, 2014
On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote:
> On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote:
>> On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:
>>> Ok, let me start with the sample code:
>>>
>>> import std.stdio;
>>> import std.json;
>>>
>>> void main() {
>>> scope(failure) writeln("FaILED!!");
>>> string jsonStr = `{ "name": "1", "type": "r" }`;
>>> auto parsed = parseJSON(jsonStr);
>>> string s = parsed["fail"].str;
>>> writeln(s == "");
>>> writeln(s is null);
>>> writeln(s);
>>> }
>>>
>>> Running "rdmd app.d" doesn't produce any output.
>>> Can anyone explain such a behavior???
>>>
>>>
>>> PS: Running dmd v2.065 on Linux x64.
>>
>> It's a bug in std.json (you should get a segfault, not no output at all)
>>
>> It is fixed now and I'm pretty sure it will be in 2.066
>>
>> std.json has been improved a lot, but I would still recommend using http://vibed.org/api/vibe.data.json/ instead
>
> perhaps "bug" is too strong a word, but it was a deficiency that is now corrected. You will get an exception thrown now and everything should work how you expect.

Maybe. But still it's not the way I expect, any time you check for non-existing property you must consider exception, which is very heavy to deal with in such a situation. I'd rather expect to get null, whenever I try to fetch non-existing property, and not an exception.

That's purely my point, and I don't claim to be right in this way. It's up to Phobos maintainers to decide how to reprent JSON parsing results.
July 24, 2014
On Thursday, 24 July 2014 at 15:42:58 UTC, Pavel wrote:
> On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote:
>> On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote:
>>> On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:
>>>> Ok, let me start with the sample code:
>>>>
>>>> import std.stdio;
>>>> import std.json;
>>>>
>>>> void main() {
>>>> scope(failure) writeln("FaILED!!");
>>>> string jsonStr = `{ "name": "1", "type": "r" }`;
>>>> auto parsed = parseJSON(jsonStr);
>>>> string s = parsed["fail"].str;
>>>> writeln(s == "");
>>>> writeln(s is null);
>>>> writeln(s);
>>>> }
>>>>
>>>> Running "rdmd app.d" doesn't produce any output.
>>>> Can anyone explain such a behavior???
>>>>
>>>>
>>>> PS: Running dmd v2.065 on Linux x64.
>>>
>>> It's a bug in std.json (you should get a segfault, not no output at all)
>>>
>>> It is fixed now and I'm pretty sure it will be in 2.066
>>>
>>> std.json has been improved a lot, but I would still recommend using http://vibed.org/api/vibe.data.json/ instead
>>
>> perhaps "bug" is too strong a word, but it was a deficiency that is now corrected. You will get an exception thrown now and everything should work how you expect.
>
> Maybe. But still it's not the way I expect, any time you check for non-existing property you must consider exception, which is very heavy to deal with in such a situation. I'd rather expect to get null, whenever I try to fetch non-existing property, and not an exception.
>
> That's purely my point, and I don't claim to be right in this way. It's up to Phobos maintainers to decide how to reprent JSON parsing results.

Also that's why you just can't write:

writeln("fail" in parsed);

As JSONValue is just a wrapper: non-native, non-intuitive.
July 24, 2014
On Thursday, 24 July 2014 at 15:42:58 UTC, Pavel wrote:
> On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote:
>> On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote:
>>> On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:
>>>> Ok, let me start with the sample code:
>>>>
>>>> import std.stdio;
>>>> import std.json;
>>>>
>>>> void main() {
>>>> scope(failure) writeln("FaILED!!");
>>>> string jsonStr = `{ "name": "1", "type": "r" }`;
>>>> auto parsed = parseJSON(jsonStr);
>>>> string s = parsed["fail"].str;
>>>> writeln(s == "");
>>>> writeln(s is null);
>>>> writeln(s);
>>>> }
>>>>
>>>> Running "rdmd app.d" doesn't produce any output.
>>>> Can anyone explain such a behavior???
>>>>
>>>>
>>>> PS: Running dmd v2.065 on Linux x64.
>>>
>>> It's a bug in std.json (you should get a segfault, not no output at all)
>>>
>>> It is fixed now and I'm pretty sure it will be in 2.066
>>>
>>> std.json has been improved a lot, but I would still recommend using http://vibed.org/api/vibe.data.json/ instead
>>
>> perhaps "bug" is too strong a word, but it was a deficiency that is now corrected. You will get an exception thrown now and everything should work how you expect.
>
> Maybe. But still it's not the way I expect, any time you check for non-existing property you must consider exception, which is very heavy to deal with in such a situation. I'd rather expect to get null, whenever I try to fetch non-existing property, and not an exception.

You can turn your json object into an AA object and then use in to check for existence (I know it is not very intuitive):

JSONValue[string] jsonAA = parsed.object;
if ( "fail" in jsonAA )
  s = jsonAA["fail"].str;



>
> That's purely my point, and I don't claim to be right in this way. It's up to Phobos maintainers to decide how to reprent JSON parsing results.

July 24, 2014
On Thursday, 24 July 2014 at 15:48:32 UTC, Edwin van Leeuwen wrote:
> On Thursday, 24 July 2014 at 15:42:58 UTC, Pavel wrote:
>> On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote:
>>> On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote:
>>>> On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:
>>>>> Ok, let me start with the sample code:
>>>>>
>>>>> import std.stdio;
>>>>> import std.json;
>>>>>
>>>>> void main() {
>>>>> scope(failure) writeln("FaILED!!");
>>>>> string jsonStr = `{ "name": "1", "type": "r" }`;
>>>>> auto parsed = parseJSON(jsonStr);
>>>>> string s = parsed["fail"].str;
>>>>> writeln(s == "");
>>>>> writeln(s is null);
>>>>> writeln(s);
>>>>> }
>>>>>
>>>>> Running "rdmd app.d" doesn't produce any output.
>>>>> Can anyone explain such a behavior???
>>>>>
>>>>>
>>>>> PS: Running dmd v2.065 on Linux x64.
>>>>
>>>> It's a bug in std.json (you should get a segfault, not no output at all)
>>>>
>>>> It is fixed now and I'm pretty sure it will be in 2.066
>>>>
>>>> std.json has been improved a lot, but I would still recommend using http://vibed.org/api/vibe.data.json/ instead
>>>
>>> perhaps "bug" is too strong a word, but it was a deficiency that is now corrected. You will get an exception thrown now and everything should work how you expect.
>>
>> Maybe. But still it's not the way I expect, any time you check for non-existing property you must consider exception, which is very heavy to deal with in such a situation. I'd rather expect to get null, whenever I try to fetch non-existing property, and not an exception.
>
> You can turn your json object into an AA object and then use in to check for existence (I know it is not very intuitive):
>
> JSONValue[string] jsonAA = parsed.object;
> if ( "fail" in jsonAA )
>   s = jsonAA["fail"].str;
>
>
>
>>
>> That's purely my point, and I don't claim to be right in this way. It's up to Phobos maintainers to decide how to reprent JSON parsing results.

Guess what, here's a new snippet:

import std.stdio;
import std.json;

void main() {
  scope(failure) writeln("FaILED!!");
  string jsonStr = `{ "name": "1", "type": "r" }`;
  auto parsed = parseJSON(jsonStr).object;
  writeln("fail" in parsed);
}

Output is:
null

WAT?!

Ofcourse, writing like:

writeln(cast(bool)("fail" in parsed));

Produces "false"... but why on earth boolean expression would output null?

PS: Sorry, for such an emotional boom, I'm so frustrated right now.
July 24, 2014
Pavel:

> writeln(cast(bool)("fail" in parsed));
>
> Produces "false"... but why on earth boolean expression would output null?

In D if you perform an associative array "in", the return isn't a boolean but a pointer. It's zero if the item is not present. And it's a valid pointer to the value if the key is present.

Bye,
bearophile
July 24, 2014
Am 24.07.2014 17:54, schrieb Pavel:
>
> Guess what, here's a new snippet:
>
> import std.stdio;
> import std.json;
>
> void main() {
>    scope(failure) writeln("FaILED!!");
>    string jsonStr = `{ "name": "1", "type": "r" }`;
>    auto parsed = parseJSON(jsonStr).object;
>    writeln("fail" in parsed);
> }
>
> Output is:
> null
>
> WAT?!
>
> Ofcourse, writing like:
>
> writeln(cast(bool)("fail" in parsed));
>
> Produces "false"... but why on earth boolean expression would output null?
>
> PS: Sorry, for such an emotional boom, I'm so frustrated right now.

Relax :-)

And see http://dlang.org/hash-map.html

"in" doesn't just return if something is in a map.
If it is, it returns a pointer to the value, otherwise null.
Thus null.

Cheers,
Daniel
July 24, 2014
On Thu, 24 Jul 2014 15:54:20 +0000, Pavel wrote:

> On Thursday, 24 July 2014 at 15:48:32 UTC, Edwin van Leeuwen wrote:
>> On Thursday, 24 July 2014 at 15:42:58 UTC, Pavel wrote:
>>> On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote:
>>>> On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote:
>>>>> On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:
>>>>>> Ok, let me start with the sample code:
>>>>>>
>>>>>> import std.stdio;
>>>>>> import std.json;
>>>>>>
>>>>>> void main() {
>>>>>> scope(failure) writeln("FaILED!!");
>>>>>> string jsonStr = `{ "name": "1", "type": "r" }`;
>>>>>> auto parsed = parseJSON(jsonStr);
>>>>>> string s = parsed["fail"].str;
>>>>>> writeln(s == "");
>>>>>> writeln(s is null);
>>>>>> writeln(s);
>>>>>> }
>>>>>>
>>>>>> Running "rdmd app.d" doesn't produce any output.
>>>>>> Can anyone explain such a behavior???
>>>>>>
>>>>>>
>>>>>> PS: Running dmd v2.065 on Linux x64.
>>>>>
>>>>> It's a bug in std.json (you should get a segfault, not no output at
>>>>> all)
>>>>>
>>>>> It is fixed now and I'm pretty sure it will be in 2.066
>>>>>
>>>>> std.json has been improved a lot, but I would still recommend using http://vibed.org/api/vibe.data.json/ instead
>>>>
>>>> perhaps "bug" is too strong a word, but it was a deficiency that is now corrected. You will get an exception thrown now and everything should work how you expect.
>>>
>>> Maybe. But still it's not the way I expect, any time you check for non-existing property you must consider exception, which is very heavy to deal with in such a situation. I'd rather expect to get null, whenever I try to fetch non-existing property, and not an exception.
>>
>> You can turn your json object into an AA object and then use in to check for existence (I know it is not very intuitive):
>>
>> JSONValue[string] jsonAA = parsed.object;
>> if ( "fail" in jsonAA )
>>   s = jsonAA["fail"].str;
>>
>>
>>
>>
>>> That's purely my point, and I don't claim to be right in this way. It's up to Phobos maintainers to decide how to reprent JSON parsing results.
> 
> Guess what, here's a new snippet:
> 
> import std.stdio;
> import std.json;
> 
> void main() {
>    scope(failure) writeln("FaILED!!");
>    string jsonStr = `{ "name": "1", "type": "r" }`;
>    auto parsed = parseJSON(jsonStr).object; writeln("fail" in parsed);
> }
> 
> Output is:
> null
> 
> WAT?!
> 
> Ofcourse, writing like:
> 
> writeln(cast(bool)("fail" in parsed));
> 
> Produces "false"... but why on earth boolean expression would output null?
> 
> PS: Sorry, for such an emotional boom, I'm so frustrated right now.

The `in` expression produces a pointer to the value in the container, not a bool.  If the key is not present in the container, it returns the null pointer.  So this test is working precisely as expected.  Here are some common idioms for working with `in` and associative arrays:

// if with declaration
if (auto vptr = "fail" in parsed.object)
    writeln("here's the value: ", *vptr);
else
    writeln("fail is not in the JSON");

// coerce to bool
writeln(!!("fail" in parsed.object));

// get the value or a default value
writeln(parsed.object.get("fail", someDefaultJson));