Page 1 of 1
JSON merge
Posted: Thu Jul 12, 2018 11:51 am
by mariosk8s
How do i merge 2 JSON objects, so that one is a sub object of the other?
Example:
Code: Select all
top = ParseJSON(#PB_Any, ReplaceString("{'foo':'bar','test':1}",
"'", Chr(34)))
sub = ParseJSON(#PB_Any, ReplaceString("{'prop1':'val1','test1':1, 'more':{ 'a':1, 'b': 'hi'}}",
"'", Chr(34)))
; here's me dreaming up API
SetJSONObject(AddJSONMember(top, "sub"), JSONValue(sub))
Is there a way to do this? So i'd end up with something like
Code: Select all
ComposeJSON(top)
{
"foo": "bar",
"test": 1,
"sub" : {
"prop1": "val1",
"test1": 1,
"more": {
"a": 1,
"b": "hi"
}
}
}
Re: JSON merge
Posted: Thu Jul 12, 2018 12:51 pm
by NicTheQuick
I am working the first time with JSON and I don't understand why I can not set an object and why neither top nor sub have a type. Then I figured out that I have to use JSONValue() before JSONType() and then sub and top are recognized as objects. But I can not use SetJSONObject() to add one of these objects to an other. I think one has to develop a small recursive procedure which runs recursively through the object to be copied and add all elements one by one to the top element.
Code: Select all
Procedure.s GetAnyValue(Value)
Select JSONType(Value)
Case #PB_JSON_Null: ProcedureReturn "null"
Case #PB_JSON_String: ProcedureReturn GetJSONString(Value)
Case #PB_JSON_Number: ProcedureReturn StrD(GetJSONDouble(Value))
Case #PB_JSON_Boolean: ProcedureReturn Str(GetJSONBoolean(Value))
Case #PB_JSON_Array: ProcedureReturn "array"
Case #PB_JSON_Object: ProcedureReturn "object"
Default: ProcedureReturn "Unknown: " + Str(JSONType(Value))
EndSelect
EndProcedure
top = ParseJSON(#PB_Any, ~"{\"foo\":\"bar\",\"test\":1}")
sub = ParseJSON(#PB_Any, ~"{\"prop1\":\"val1\",\"test1\":1, \"more\":{ \"a\":1, \"b\": \"hi\"}}")
Debug GetAnyValue(JSONValue(top))
Debug GetAnyValue(JSONValue(sub))
newSub = AddJSONMember(JSONValue(top), "sub")
;SetJSONObject(newSub, sub)
Debug ComposeJSON(top, #PB_JSON_PrettyPrint)
So it would be nice if there were a second parameter for SetJSONObject(). I don't understand why someone wants to create an object with no objects.
Re: JSON merge
Posted: Thu Jul 12, 2018 3:53 pm
by mariosk8s
So in the absence of merge functionality i created a clone function.
This is obviously not performant, but ok for small stuff.
Code: Select all
Procedure jsonClone(jSrc, jDest)
Select JSONType(jSrc)
Case #PB_JSON_Null:
SetJSONNull(jDest)
Case #PB_JSON_String:
SetJSONString(jDest, GetJSONString(jSrc))
Case #PB_JSON_Number:
SetJSONDouble(jDest, GetJSONDouble(jSrc))
Case #PB_JSON_Boolean:
SetJSONBoolean(jDest, GetJSONBoolean(jSrc))
Case #PB_JSON_Array:
Protected i, len = JSONArraySize(jSrc)
SetJSONArray(jDest)
For i = 0 To (len - 1)
Protected ja = GetJSONElement(jSrc, i)
Protected ca = AddJSONElement(jDest)
jsonClone(ja, ca)
Next
Case #PB_JSON_Object:
SetJSONObject(jDest)
If ExamineJSONMembers(jSrc)
While NextJSONMember(jSrc)
Protected key.s = JSONMemberKey(jSrc)
Protected jo = JSONMemberValue(jSrc)
Protected co = AddJSONMember(jDest, key)
jsonClone(jo, co)
Wend
EndIf
Default:
EndSelect
EndProcedure
Usage would like this
Code: Select all
top = ParseJSON(#PB_Any, ~"{\"foo\":\"bar\",\"test\":1}")
sub = ParseJSON(#PB_Any, ~"{\"prop1\":\"val1\",\"test1\":1, \"more\":{ \"a\":1, \"b\": \"hi\"}}")
Debug ComposeJSON(top, #PB_JSON_PrettyPrint)
Debug ComposeJSON(sub, #PB_JSON_PrettyPrint)
no = AddJSONMember(JSONValue(top), "sub")
jsonClone(JSONValue(sub), no)
Debug ComposeJSON(top, #PB_JSON_PrettyPrint)
sub2 = ParseJSON(#PB_Any, ~"[\"#1\", 2, {\"three\": true}]")
Debug ComposeJSON(sub2, #PB_JSON_PrettyPrint)
no2 = AddJSONMember(JSONValue(top), "sub2")
jsonClone(JSONValue(sub2), no2)
Debug ComposeJSON(top, #PB_JSON_PrettyPrint)
Re: JSON merge
Posted: Thu Jul 12, 2018 4:41 pm
by NicTheQuick
Nice!

Re: JSON merge
Posted: Fri Jul 13, 2018 4:20 pm
by Kwai chang caine
Cool function
Thanks Mariosk8s for sharing

Re: JSON merge
Posted: Sat Jul 14, 2018 7:23 am
by Little John
Personally, I never have stumbled across this problem.
Anyway, there is obviously some functionality missing in PB in this regard.
@mariosk8s:
Thank you for pointing this problem out, and for the code that solves it.