www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - copy a JSONValue

reply Alex <sascha.orlov gmail.com> writes:
Hi everybody,
I'm little at loss: as documented, a JSONValue is only shallow 
copied:

void main()
{
     import std.json;
     import std.stdio;

     string s = "{ \"language\": \"D\", \"rating\": 3.14, 
\"code\": 42 }";
     JSONValue j = parseJSON(s);
     writeln("code: ", j["code"].integer);

     auto j2 = j;
     j2["code"] = 43;
     writeln("code of j2: ", j2["code"].integer);
     writeln("code of j: ", j["code"].integer);
}

So the effect that the code of "j" is altered was expected.

The question is: how to make a deep copy of a JSONValue? Is there 
a simple way without copying the source string around? Or, would 
this be the simplest way?

Thanks in advance
Alex
Aug 25 2016
next sibling parent reply Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Dne 26.8.2016 v 08:56 Alex via Digitalmars-d-learn napsal(a):
 void main()
 {
     import std.json;
     import std.stdio;

     string s = "{ \"language\": \"D\", \"rating\": 3.14, \"code\": 42 }";
     JSONValue j = parseJSON(s);
     writeln("code: ", j["code"].integer);

     auto j2 = j;
     j2["code"] = 43;
     writeln("code of j2: ", j2["code"].integer);
     writeln("code of j: ", j["code"].integer);
 } 
void main() { import std.json; import std.stdio; string s = "{ \"language\": \"D\", \"rating\": 3.14, \"code\": 42 }"; JSONValue j = parseJSON(s); writeln("code: ", j["code"].integer); auto j2 = j.toString.parseJSON; j2["code"] = 43; writeln("code of j2: ", j2["code"].integer); writeln("code of j: ", j["code"].integer); }
Aug 26 2016
parent reply Alex <sascha.orlov gmail.com> writes:
On Friday, 26 August 2016 at 07:20:00 UTC, Daniel Kozak wrote:
     auto j2 = j.toString.parseJSON;
ha! cool! thanks! :)
Aug 26 2016
parent Alex <sascha.orlov gmail.com> writes:
On Friday, 26 August 2016 at 08:21:14 UTC, Alex wrote:
 On Friday, 26 August 2016 at 07:20:00 UTC, Daniel Kozak wrote:
     auto j2 = j.toString.parseJSON;
ha! cool! thanks! :)
found a bug... https://issues.dlang.org/show_bug.cgi?id=16432 not very serious... but not found yet? ;)
Aug 26 2016
prev sibling parent reply Daniel Kozak <kozzi11 gmail.com> writes:
On Friday, 26 August 2016 at 06:56:06 UTC, Alex wrote:
 Hi everybody,
 I'm little at loss: as documented, a JSONValue is only shallow 
 copied:

 ...

 So the effect that the code of "j" is altered was expected.

 The question is: how to make a deep copy of a JSONValue? Is 
 there a simple way without copying the source string around? 
 Or, would this be the simplest way?

 Thanks in advance
 Alex
Another way is to implement deepCopy by yourself (something like below) import std.json; import std.stdio; JSONValue deepCopy(ref JSONValue val) { JSONValue newVal; switch(val.type) { case JSON_TYPE.STRING: newVal = JSONValue(val.str.idup); break; case JSON_TYPE.OBJECT: foreach (string key, value; val) { newVal[key] = value.deepCopy; } break; case JSON_TYPE.ARRAY: foreach (size_t index, value; val) { newVal[index] = value.deepCopy; } break; default: newVal = val; } return newVal; } void main() { string s = "{ \"language\": \"D\", \"rating\": 3.14, \"code\": 42 }"; JSONValue j = parseJSON(s); writeln("code: ", j["code"].integer); auto j2 = j.deepCopy; j2["code"] = 43; writeln("code of j2: ", j2["code"].integer); writeln("code of j: ", j["code"].integer); }
Aug 26 2016
parent Alex <sascha.orlov gmail.com> writes:
On Friday, 26 August 2016 at 07:46:13 UTC, Daniel Kozak wrote:
 Another way is to implement deepCopy by yourself (something 
 like below)

 import std.json;
 import std.stdio;

 JSONValue deepCopy(ref JSONValue val)
 {
     JSONValue newVal;
     switch(val.type)
     {
         case JSON_TYPE.STRING:
             newVal = JSONValue(val.str.idup);
             break;
         case JSON_TYPE.OBJECT:
             foreach (string key, value; val)
             {
                 newVal[key] = value.deepCopy;
             }
             break;
         case JSON_TYPE.ARRAY:
             foreach (size_t index, value; val)
             {
                 newVal[index] = value.deepCopy;
             }
             break;
         default:
             newVal = val;

     }
     return newVal;
 }

 void main()
 {
     string s = "{ \"language\": \"D\", \"rating\": 3.14, 
 \"code\": 42 }";
     JSONValue j = parseJSON(s);
     writeln("code: ", j["code"].integer);

     auto j2 = j.deepCopy;
     j2["code"] = 43;
     writeln("code of j2: ", j2["code"].integer);
     writeln("code of j: ", j["code"].integer);
 }
Yeah... I thought that i would have to implement something like this... And wanted to avoid this... So, yes, I think this is the more convincing way, but in my case the --> toString --> toJson conversion is enough... Thanks for help :)
Aug 26 2016