Re: std.json dynamic initialization of JSONValue
Am 06.12.2011 22:30, schrieb Kai Meyer: I posted this on D.learn, but got no responses. I'm hoping it's because I'm asking the wrong crowd. I'm finding std.json extremely well written, with one glaring exception. I can't seem to figure out how to do this: JSONValue root = JSONValue(null, JSON_TYPE.OBJECT); root.object["first_object"] = JSONValue(null, JSON_TYPE.OBJECT); root.object["first_string"] = JSONValue("first_string", JSON_TYPE.STRING); which would decode to: {"first_object":{},"first_string":"first_string"} What I end up having to do is: JSONValue root; root.type = JSON_TYPE.OBJECT; root.object["first_object"] = JSONValue(); root.object["first_object"].type = JSON_TYPE.OBJECT; root.object["first_string"] = JSON_Value(); root.object["first_string"].type = JSON_TYPE.STRING; root.object["first_string"].str = "first_string"; That just feels like I'm doing it wrong. Is there a way to dynamically initialize a JSONValue struct? If I try to intialize the JSONValue object with anything other than simply null, or empty string, I either get a compile error or a segfault at run-time. root.object["first_object"] = JSONValue(null, JSON_TYPE.OBJECT); compile error: Error: overlapping initialization for integer root.object["first_string"] = JSONValue("first_string"); run-time segfault. Any ideas? That's the reason why I use libdjson (well the bug with dmd 2.053 made me switch, but I didn't switch back): https://256.makerslocal.org/wiki/Libdjson
Re: std.json dynamic initialization of JSONValue
Robert Jacques; I like your modules a lot. I'm sure it will be a bit of a pain to integrate it into my existing codebase, but they look like it'd be worth it!
Re: std.json dynamic initialization of JSONValue
On Tue, 06 Dec 2011 19:15:26 -0500, Jonathan M Davis wrote: On Tuesday, December 06, 2011 18:26:39 Adam D. Ruppe wrote: Kai Meyer Wrote: > I like it. Any reason something like this doesn't already exist in > std.json? I think it's just that nobody has done updates to std.json for a while, but I don't really know. I believe that Robert Jacques has a revised version of std.json that he intends to put up for review, but it relies on changes that he's made to std.variant which also need be reviewed. - Jonathan M Davis Correct. Andrei suggested that since JSONValue is a tagged union, it should really use std.Variant.Algebraic as its representation, which necessitated fixing both Variant and Algebraic so that was possible. The code and documentation links are below if you'd like to try it out/comment on it. The only thing unintuitive in my revision from your use case is creating an empty JSON object or array: JSON.Value myObject = JSON.Value[string].init; JSON.Value myArray = JSON.Value[].init; Since this is undocumented :( I think I'm going to add some aliases (JSON.Object_init, JSON.Array_init) to simplify things for people. https://jshare.johnshopkins.edu/rjacque2/public_html/json2.mht https://jshare.johnshopkins.edu/rjacque2/public_html/variant.mht https://jshare.johnshopkins.edu/rjacque2/public_html/json2.d https://jshare.johnshopkins.edu/rjacque2/public_html/variant.d
Re: std.json dynamic initialization of JSONValue
On Tuesday, December 06, 2011 18:26:39 Adam D. Ruppe wrote: > Kai Meyer Wrote: > > I like it. Any reason something like this doesn't already exist in > > std.json? > I think it's just that nobody has done updates to std.json for a while, but > I don't really know. I believe that Robert Jacques has a revised version of std.json that he intends to put up for review, but it relies on changes that he's made to std.variant which also need be reviewed. - Jonathan M Davis
Re: std.json dynamic initialization of JSONValue
Kai Meyer Wrote: > I like it. Any reason something like this doesn't already exist in std.json? I think it's just that nobody has done updates to std.json for a while, but I don't really know.
Re: std.json dynamic initialization of JSONValue
On 12/06/2011 02:42 PM, Adam D. Ruppe wrote: I could swear I replied in the other group... must have gotten lost in the series of tubes. Anyway, I think std.json is easiest to use with a little template wrapper instead of making JSONValues directly. Try this on for size: = import std.json; import std.conv; import std.traits; JSONValue toJsonValue(T)(T a) { JSONValue val; static if(is(T == typeof(null))) { val.type = JSON_TYPE.NULL; } else static if(is(T == JSONValue)) { val = a; } else static if(isIntegral!(T)) { val.type = JSON_TYPE.INTEGER; val.integer = to!long(a); } else static if(isFloatingPoint!(T)) { val.type = JSON_TYPE.FLOAT; val.floating = to!real(a); } else static if(is(T == bool)) { if(a == true) val.type = JSON_TYPE.TRUE; if(a == false) val.type = JSON_TYPE.FALSE; } else static if(isSomeString!(T)) { val.type = JSON_TYPE.STRING; val.str = to!string(a); } else static if(isAssociativeArray!(T)) { val.type = JSON_TYPE.OBJECT; foreach(k, v; a) { val.object[to!string(k)] = toJsonValue(v); } } else static if(isArray!(T)) { val.type = JSON_TYPE.ARRAY; val.array.length = a.length; foreach(i, v; a) { val.array[i] = toJsonValue(v); } } else static if(is(T == struct)) { // also can do all members of a struct... val.type = JSON_TYPE.OBJECT; foreach(i, member; a.tupleof) { string name = a.tupleof[i].stringof[2..$]; static if(a.tupleof[i].stringof[2] != '_') val.object[name] = toJsonValue!(typeof(member), R)(member, formatToStringAs, api); } } else { /* our catch all is to just do strings */ val.type = JSON_TYPE.STRING; val.str = to!string(a); } return val; } string toJson(T)(T a) { auto v = toJsonValue(a); return toJSON(&v); } /* usage example */ import std.stdio; void main() { writeln(toJson(["message": "Hello, world!"])); } == Then, you can either use toJsonValue() to fill in an object similar to what you were doing before, or use toJson() to skip right to having a string from a struct, an associative array, or many other D types. I like it. Any reason something like this doesn't already exist in std.json? -Kai Meyer
Re: std.json dynamic initialization of JSONValue
Adam D. Ruppe Wrote: > val.object[name] = toJsonValue!(typeof(member), > R)(member, formatToStringAs, api); Whoops, that should have been val.object[name] = toJsonValue(member); (I copy pasted this out of my web.d module, which can add a toString() method to the json too, so it's a little more complicated. And probably useless.)
Re: std.json dynamic initialization of JSONValue
I could swear I replied in the other group... must have gotten lost in the series of tubes. Anyway, I think std.json is easiest to use with a little template wrapper instead of making JSONValues directly. Try this on for size: = import std.json; import std.conv; import std.traits; JSONValue toJsonValue(T)(T a) { JSONValue val; static if(is(T == typeof(null))) { val.type = JSON_TYPE.NULL; } else static if(is(T == JSONValue)) { val = a; } else static if(isIntegral!(T)) { val.type = JSON_TYPE.INTEGER; val.integer = to!long(a); } else static if(isFloatingPoint!(T)) { val.type = JSON_TYPE.FLOAT; val.floating = to!real(a); } else static if(is(T == bool)) { if(a == true) val.type = JSON_TYPE.TRUE; if(a == false) val.type = JSON_TYPE.FALSE; } else static if(isSomeString!(T)) { val.type = JSON_TYPE.STRING; val.str = to!string(a); } else static if(isAssociativeArray!(T)) { val.type = JSON_TYPE.OBJECT; foreach(k, v; a) { val.object[to!string(k)] = toJsonValue(v); } } else static if(isArray!(T)) { val.type = JSON_TYPE.ARRAY; val.array.length = a.length; foreach(i, v; a) { val.array[i] = toJsonValue(v); } } else static if(is(T == struct)) { // also can do all members of a struct... val.type = JSON_TYPE.OBJECT; foreach(i, member; a.tupleof) { string name = a.tupleof[i].stringof[2..$]; static if(a.tupleof[i].stringof[2] != '_') val.object[name] = toJsonValue!(typeof(member), R)(member, formatToStringAs, api); } } else { /* our catch all is to just do strings */ val.type = JSON_TYPE.STRING; val.str = to!string(a); } return val; } string toJson(T)(T a) { auto v = toJsonValue(a); return toJSON(&v); } /* usage example */ import std.stdio; void main() { writeln(toJson(["message": "Hello, world!"])); } == Then, you can either use toJsonValue() to fill in an object similar to what you were doing before, or use toJson() to skip right to having a string from a struct, an associative array, or many other D types.