digitalmars.D - std.json dynamic initialization of JSONValue
- Kai Meyer (27/27) Dec 06 2011 I posted this on D.learn, but got no responses. I'm hoping it's because
- Adam D. Ruppe (67/67) Dec 06 2011 I could swear I replied in the other group... must have gotten lost in t...
- Adam D. Ruppe (5/6) Dec 06 2011 Whoops, that should have been
- Kai Meyer (3/70) Dec 06 2011 I like it. Any reason something like this doesn't already exist in std.j...
- Adam D. Ruppe (3/4) Dec 06 2011 I think it's just that nobody has done updates to std.json for a while, ...
- Jonathan M Davis (5/10) Dec 06 2011 I believe that Robert Jacques has a revised version of std.json that he
- Robert Jacques (9/19) Dec 06 2011 Correct. Andrei suggested that since JSONValue is a tagged union, it sho...
- Adam D. Ruppe (3/3) Dec 06 2011 Robert Jacques;
- David (4/31) Dec 07 2011 That's the reason why I use libdjson (well the bug with dmd 2.053 made
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?
Dec 06 2011
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.
Dec 06 2011
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.)
Dec 06 2011
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
Dec 06 2011
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.
Dec 06 2011
On Tuesday, December 06, 2011 18:26:39 Adam D. Ruppe wrote:Kai Meyer Wrote: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 DavisI 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.
Dec 06 2011
On Tue, 06 Dec 2011 19:15:26 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Tuesday, December 06, 2011 18:26:39 Adam D. Ruppe wrote: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.dKai Meyer Wrote: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 DavisI 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.
Dec 06 2011
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!
Dec 06 2011
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
Dec 07 2011