digitalmars.D.learn - D JSON (WAT?!)
- Pavel (15/15) Jul 24 2014 Ok, let me start with the sample code:
- Justin Whear (4/24) Jul 24 2014 That's because it produces a segmentation fault, which rdmd masks for
- Pavel (15/41) Jul 24 2014 Here's phobos code from github:
- Adam D. Ruppe (5/6) Jul 24 2014 Since there is no entry "fail" in the object, it returns a null
- bearophile (4/5) Jul 24 2014 Is something like the get() function usable here?
- Pavel (7/13) Jul 24 2014 Ok, added:
- Daniel Gibson (2/17) Jul 24 2014 "is" instead of "==" ?
- Pavel (2/28) Jul 24 2014 Nope, the compiler still complains.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/10) Jul 24 2014 Comparing against null should be done with the 'is' operator, not the ==...
- Pavel (4/19) Jul 24 2014 My compiler disagreed:
- John Colvin (6/21) Jul 24 2014 It's a bug in std.json (you should get a segfault, not no output
- John Colvin (4/30) Jul 24 2014 perhaps "bug" is too strong a word, but it was a deficiency that
- Pavel (9/42) Jul 24 2014 Maybe. But still it's not the way I expect, any time you check
- Pavel (4/47) Jul 24 2014 Also that's why you just can't write:
- Edwin van Leeuwen (6/49) Jul 24 2014 You can turn your json object into an AA object and then use in
- Pavel (20/71) Jul 24 2014 Guess what, here's a new snippet:
- bearophile (6/9) Jul 24 2014 In D if you perform an associative array "in", the return isn't a
- Daniel Gibson (8/24) Jul 24 2014 Relax :-)
- Pavel (5/40) Jul 24 2014 Thanks to all you folks who explained "in" operator for me. My
- Justin Whear (6/10) Jul 24 2014 The following are valid JSON:
- Pavel (3/16) Jul 24 2014 Oh, man! You're wrong!!! Read: http://www.json.org/, and try
- Justin Whear (10/27) Jul 24 2014 Nope, while the spec calls out objects and arrays as the structural
- Ary Borenszweig (13/23) Jul 24 2014 Nope, a JSON can only be an array or an object (hash).
- Justin Whear (4/5) Jul 24 2014 Ary, can you point out the place in the spec where this is specified?
- Ary Borenszweig (7/12) Jul 24 2014 You are right, my bad. According to Wikipedia (which has links to RFCs):
- Pavel (3/22) Jul 24 2014 Sorry, Justin Whear, you were right, I was wrong. Yep, now it's
- Pavel (4/17) Jul 24 2014 Now we figured it out about JSON, but in that case:
- Justin Whear (8/25) Jul 25 2014 While I suspect the reason is simply historical, it might be a type-
- Ary Borenszweig (4/29) Jul 25 2014 Or use Algebraic, but it currently doesn't support recursive type
- Meta (10/12) Jul 25 2014 Algebraic does support recursive type definitions.
- Kagamin (3/3) Jul 26 2014 AFAIK, Variant is not transparent. You can't write
- Pavel (11/24) Aug 08 2014 auto json4 = parseJSON(`true`);
- Justin Whear (4/15) Aug 08 2014 That's right. Perhaps we need an `asBool` function or even an
- Justin Whear (14/95) Jul 24 2014 The `in` expression produces a pointer to the value in the container, no...
- H. S. Teoh via Digitalmars-d-learn (10/32) Jul 24 2014 It's not a boolean expression. The 'in' operator returns a pointer.
- Pavel (19/52) Jul 24 2014 Thanks once again. Now I finally get this thing done with code
- John Colvin (12/88) Jul 24 2014 The in operator in d returns a pointer to the element found or
- Pavel (7/33) Jul 24 2014 I'm pretty sure it's improving, but it has that "Java" disease,
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.
Jul 24 2014
On Thu, 24 Jul 2014 15:15:36 +0000, 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.That's because it produces a segmentation fault, which rdmd masks for some reason. The `parsed["fail"]` should throw a range bounds exception-- not sure why it's not.
Jul 24 2014
On Thursday, 24 July 2014 at 15:20:58 UTC, Justin Whear wrote:On Thu, 24 Jul 2014 15:15:36 +0000, Pavel wrote:Here's phobos code from github: /// Hash syntax for json objects. /// Throws $(D JSONException) if $(D type) is not $(D JSON_TYPE.OBJECT). ref inout(JSONValue) opIndex(string k) inout { enforceEx!JSONException(type == JSON_TYPE.OBJECT, "JSONValue is not an object"); return *enforceEx!JSONException(k in store.object, "Key not found: " ~ k); } Added in https://github.com/D-Programming-Language/phobos/commit/13fbd451bcca923cf8d1028495e58aa88cc7efeb Maybe phobos is not up to date for me???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.That's because it produces a segmentation fault, which rdmd masks for some reason. The `parsed["fail"]` should throw a range bounds exception-- not sure why it's not.
Jul 24 2014
On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:string s = parsed["fail"].str;Since there is no entry "fail" in the object, it returns a null JSON_VALUE pointer. Trying to get the string out of it is then seen as a null pointer access and kills the program. Check for null on a key before trying to get a value out.
Jul 24 2014
Adam D. Ruppe:Check for null on a key before trying to get a value out.Is something like the get() function usable here? Bye, bearophile
Jul 24 2014
On Thursday, 24 July 2014 at 15:22:46 UTC, Adam D. Ruppe wrote:On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:Ok, added: writeln(parsed["fail"] == null); Now compiler complains: Error: incompatible types for ((parsed.opIndex("fail")) == (null)): 'JSONValue' and 'typeof(null)' WAT?!string s = parsed["fail"].str;Since there is no entry "fail" in the object, it returns a null JSON_VALUE pointer. Trying to get the string out of it is then seen as a null pointer access and kills the program. Check for null on a key before trying to get a value out.
Jul 24 2014
Am 24.07.2014 17:29, schrieb Pavel:On Thursday, 24 July 2014 at 15:22:46 UTC, Adam D. Ruppe wrote:"is" instead of "==" ?On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:Ok, added: writeln(parsed["fail"] == null); Now compiler complains: Error: incompatible types for ((parsed.opIndex("fail")) == (null)): 'JSONValue' and 'typeof(null)' WAT?!string s = parsed["fail"].str;Since there is no entry "fail" in the object, it returns a null JSON_VALUE pointer. Trying to get the string out of it is then seen as a null pointer access and kills the program. Check for null on a key before trying to get a value out.
Jul 24 2014
On Thursday, 24 July 2014 at 15:31:30 UTC, Daniel Gibson wrote:Am 24.07.2014 17:29, schrieb Pavel:Nope, the compiler still complains.On Thursday, 24 July 2014 at 15:22:46 UTC, Adam D. Ruppe wrote:"is" instead of "==" ?On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote:Ok, added: writeln(parsed["fail"] == null); Now compiler complains: Error: incompatible types for ((parsed.opIndex("fail")) == (null)): 'JSONValue' and 'typeof(null)' WAT?!string s = parsed["fail"].str;Since there is no entry "fail" in the object, it returns a null JSON_VALUE pointer. Trying to get the string out of it is then seen as a null pointer access and kills the program. Check for null on a key before trying to get a value out.
Jul 24 2014
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
Jul 24 2014
On Thursday, 24 July 2014 at 15:34:22 UTC, Ali Çehreli wrote:On 07/24/2014 08:29 AM, Pavel wrote:My compiler disagreed: app.d(8): Error: incompatible types for ((parsed.opIndex("fail")) is (null)): 'JSONValue' and 'typeof(null)'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
Jul 24 2014
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
Jul 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: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.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
Jul 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: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.On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote: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.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
Jul 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:Also that's why you just can't write: writeln("fail" in parsed); As JSONValue is just a wrapper: non-native, non-intuitive.On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote: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.On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote: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.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
Jul 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: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;On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote: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.On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote: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.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/ insteadThat'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.
Jul 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: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.On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote: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;On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote: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.On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote: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.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/ insteadThat'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.
Jul 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
Jul 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
Jul 24 2014
On Thursday, 24 July 2014 at 15:59:52 UTC, Daniel Gibson wrote:Am 24.07.2014 17:54, schrieb Pavel:Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?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
Jul 24 2014
On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Jul 24 2014
On Thursday, 24 July 2014 at 16:09:25 UTC, Justin Whear wrote:On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:Oh, man! You're wrong!!! Read: http://www.json.org/, and try putting "1" or "foo" as JSON string here: http://jsonlint.com/Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Jul 24 2014
On Thu, 24 Jul 2014 16:14:15 +0000, Pavel wrote:On Thursday, 24 July 2014 at 16:09:25 UTC, Justin Whear wrote:Nope, while the spec calls out objects and arrays as the structural elements of JSON, it never requires (anywhere that I can find) that a complete JSON document have one of these at the root. A valid JSON value is defined as "A JSON value can be an object, array, number, string, true, false, or null"[1] Thus the parseJSON function is defined as parsing as JSONValue. 1 http://www.ecma-international.org/publications/files/ECMA-ST/ ECMA-404.pdf, p2On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:Oh, man! You're wrong!!! Read: http://www.json.org/, and try putting "1" or "foo" as JSON string here: http://jsonlint.com/Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Jul 24 2014
On 7/24/14, 1:09 PM, Justin Whear wrote:On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:Nope, a JSON can only be an array or an object (hash). In Crystal we have this definition: alias JsonType = Nil | Bool | Int64 | Float64 | String | Array(JsonType) | Hash(String, JsonType) (note that this is a recursive type definition) Then when you do Json.parse you get a value whose type is Array(JsonType) | Hash(String, JsonType). The good thing about this is that Json.parse gives you types that already exist: Array, Hash, Int64, etc. No need to define extra types and no need for users to learn a new API with new types. Wouldn't something like this be better to do in D? That is, return something that is an array or an associative array...Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Jul 24 2014
On Thu, 24 Jul 2014 13:49:27 -0300, Ary Borenszweig wrote:Nope, a JSON can only be an array or an object (hash).Ary, can you point out the place in the spec where this is specified? Not to be pedantic, but the spec only seems to define a "JSON value", not a "JSON document".
Jul 24 2014
On 7/24/14, 1:58 PM, Justin Whear wrote:On Thu, 24 Jul 2014 13:49:27 -0300, Ary Borenszweig wrote:You are right, my bad. According to Wikipedia (which has links to RFCs): Early versions of JSON (such as specified by RFC 4627) required that a valid JSON "document" must consist of only an object or an array type—though they could contain other types within them. This restriction was relaxed starting with RFC 7158, so that a JSON document may consist entirely of any possible JSON typed value.Nope, a JSON can only be an array or an object (hash).Ary, can you point out the place in the spec where this is specified? Not to be pedantic, but the spec only seems to define a "JSON value", not a "JSON document".
Jul 24 2014
On Thursday, 24 July 2014 at 18:49:27 UTC, Ary Borenszweig wrote:On 7/24/14, 1:58 PM, Justin Whear wrote:Sorry, Justin Whear, you were right, I was wrong. Yep, now it's pretty clear why there is JSONValue.On Thu, 24 Jul 2014 13:49:27 -0300, Ary Borenszweig wrote:You are right, my bad. According to Wikipedia (which has links to RFCs): Early versions of JSON (such as specified by RFC 4627) required that a valid JSON "document" must consist of only an object or an array type—though they could contain other types within them. This restriction was relaxed starting with RFC 7158, so that a JSON document may consist entirely of any possible JSON typed value.Nope, a JSON can only be an array or an object (hash).Ary, can you point out the place in the spec where this is specified? Not to be pedantic, but the spec only seems to define a "JSON value", not a "JSON document".
Jul 24 2014
On Thursday, 24 July 2014 at 16:09:25 UTC, Justin Whear wrote:On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:Now we figured it out about JSON, but in that case: Why not just use std.variant.Variant construct instead of JSONValue?Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Jul 24 2014
On Thu, 24 Jul 2014 22:00:43 +0000, Pavel wrote:On Thursday, 24 July 2014 at 16:09:25 UTC, Justin Whear wrote:While I suspect the reason is simply historical, it might be a type- safety/information problem as well. Variant can store values of essentially any type whereas JSON is strictly limited to a handful of simple types. Going from a JSON string to Variant might not be troublesome, but going from Variant to JSON string almost certainly would. That said, if you think it's worth it, I'd be up for reviewing a revamped std.json.On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:Now we figured it out about JSON, but in that case: Why not just use std.variant.Variant construct instead of JSONValue?Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Jul 25 2014
On 7/25/14, 1:06 PM, Justin Whear wrote:On Thu, 24 Jul 2014 22:00:43 +0000, Pavel wrote:Or use Algebraic, but it currently doesn't support recursive type definitions. I think this would be the best way.On Thursday, 24 July 2014 at 16:09:25 UTC, Justin Whear wrote:While I suspect the reason is simply historical, it might be a type- safety/information problem as well. Variant can store values of essentially any type whereas JSON is strictly limited to a handful of simple types. Going from a JSON string to Variant might not be troublesome, but going from Variant to JSON string almost certainly would. That said, if you think it's worth it, I'd be up for reviewing a revamped std.json.On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:Now we figured it out about JSON, but in that case: Why not just use std.variant.Variant construct instead of JSONValue?Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Jul 25 2014
On Saturday, 26 July 2014 at 00:26:08 UTC, Ary Borenszweig wrote:Or use Algebraic, but it currently doesn't support recursive type definitions.Algebraic does support recursive type definitions. import std.variant; alias Rec = Algebraic!(int, This*); void main() { //I'm not sure why this works auto i = Rec(Rec(Rec(1))); i = Rec(new Rec(new Rec(1))); }
Jul 25 2014
AFAIK, Variant is not transparent. You can't write parsed["field1"]["field2"], it should be parsed["field1"].get!(Variant[string])["field2"].
Jul 26 2014
On Thursday, 24 July 2014 at 16:09:25 UTC, Justin Whear wrote:On Thu, 24 Jul 2014 16:04:01 +0000, Pavel wrote:auto json4 = parseJSON(`true`); This is a valid JSON also. I know that as per JSON spec there's no boolean type specified, only separate true and false values, which are specified as type in http://dlang.org/library/std/json/JSON_TYPE.html, so I guess the only way to check boolean in JSONValue it is to write: if (json4.type == JSON_TYPE.True) { } else { } Am I right?Thanks to all you folks who explained "in" operator for me. My bad. Let's focus on the real problem, which is JSON wrapper class. Is it needed? Wouldn't it be better to get AA from parseJSON?The following are valid JSON: auto json1 = parseJSON(`1`); auto json2 = parseJSON(`"foo"`); auto json3 = parseJSON(`[1, 2, 3]`); None of these fit naturally into an JSONValue[string] return type.
Aug 08 2014
On Fri, 08 Aug 2014 14:07:33 +0000, Pavel wrote:I know that as per JSON spec there's no boolean type specified, only separate true and false values, which are specified as type in http://dlang.org/library/std/json/JSON_TYPE.html, so I guess the only way to check boolean in JSONValue it is to write: if (json4.type == JSON_TYPE.True) { } else { } Am I right?That's right. Perhaps we need an `asBool` function or even an opCast!bool that returns false on FALSE, NULL, and possibly empty strings/ objects/arrays.
Aug 08 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: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));On Thursday, 24 July 2014 at 15:42:58 UTC, Pavel wrote: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.On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote: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;On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote: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.On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote: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.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/ insteadThat'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.
Jul 24 2014
On Thu, Jul 24, 2014 at 03:54:20PM +0000, Pavel via Digitalmars-d-learn wrote: [...]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?It's not a boolean expression. The 'in' operator returns a pointer. Rationale: avoid double lookups, for example: if (auto ptr = "key" in assocArray) { doSomething(*ptr); } T -- The right half of the brain controls the left half of the body. This means that only left-handed people are in their right mind. -- Manoj Srivastava
Jul 24 2014
On Thursday, 24 July 2014 at 16:02:12 UTC, H. S. Teoh via Digitalmars-d-learn wrote:On Thu, Jul 24, 2014 at 03:54:20PM +0000, Pavel via Digitalmars-d-learn wrote: [...]Thanks once again. Now I finally get this thing done with code like this: import std.stdio; import std.json; void main() { scope(failure) writeln("Failure!!"); string jsonStr = `{ "name": "1", "type": "r" }`; auto parsed = parseJSON(jsonStr).object; auto found = "fail" in parsed; if (found !is null) { string s = found.str; writeln(s); } else { writeln("No such key"); } } Still focus on wrapper class discussion :)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?It's not a boolean expression. The 'in' operator returns a pointer. Rationale: avoid double lookups, for example: if (auto ptr = "key" in assocArray) { doSomething(*ptr); } T
Jul 24 2014
On Thursday, 24 July 2014 at 15:54:21 UTC, Pavel wrote:On Thursday, 24 July 2014 at 15:48:32 UTC, Edwin van Leeuwen wrote:The in operator in d returns a pointer to the element found or null. This might be a little confusing at first* but it makes sense for efficiency reasons. There is often a lot overlap between the work needed to test for presence and the work needed to fetch an element. For types where fetching elements is a significant extra cost you can always define a `bool contains(K key) { /* ... */ }` so a user can avoid this cost when appropriate. *although to be honest it's just a different reading: `b in c` can be read as "the b in c" or "is b in c?"On Thursday, 24 July 2014 at 15:42:58 UTC, Pavel wrote: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.On Thursday, 24 July 2014 at 15:38:06 UTC, John Colvin wrote: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;On Thursday, 24 July 2014 at 15:32:29 UTC, John Colvin wrote: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.On Thursday, 24 July 2014 at 15:15:37 UTC, Pavel wrote: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.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/ insteadThat'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.
Jul 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: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.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
Jul 24 2014