Thread overview
copy a JSONValue
Aug 26, 2016
Alex
Aug 26, 2016
Daniel Kozak
Aug 26, 2016
Alex
Aug 26, 2016
Alex
Aug 26, 2016
Daniel Kozak
Aug 26, 2016
Alex
August 26, 2016
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
August 26, 2016

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);
}
August 26, 2016
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);
}


August 26, 2016
On Friday, 26 August 2016 at 07:20:00 UTC, Daniel Kozak wrote:
>     auto j2 = j.toString.parseJSON;

ha! cool! thanks! :)
August 26, 2016
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 :)
August 26, 2016
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? ;)