Page 1 of 2
[probably trivial] Access JSON objects members
Posted: Mon Mar 14, 2016 4:09 pm
by bbanelli
Greetings,
I apologize for asking stupid questions, but I'm really confused with this one - here's the JSON I parse:
Code: Select all
{
"product": {
"x" : "text",
"y" : false,
"z" : true,
}
}
I get it as a string, and after the following code:
Code: Select all
If ParseJSON(0, JSONData)
ObjectValue = JSONValue(0)
If ExamineJSONMembers(ObjectValue)
While NextJSONMember(ObjectValue)
Debug JSONMemberKey(ObjectValue)
Wend
EndIf
EndIf
the only thing I get out is "product".
But how do I access elements x, y and z? And so on, if for example, element x has another {} pattern below it...
Sorry for missing nomenclature, I'm just getting a feel of JSON stuff...
Re: [probably trivial] Access JSON objects members
Posted: Mon Mar 14, 2016 4:31 pm
by Little John
Are you looking for something like
this?
The procedure TraverseJSON() should work for all kinds of dynamic JSON data.
Re: [probably trivial] Access JSON objects members
Posted: Tue Mar 15, 2016 12:05 am
by Lunasole
Hah, I understand how you feel trying to do something with this.
The stupid is JSON format itself, not a question. I definitely just hate this web-trash, also last time had to work with it a lot too. Even XML is much better.
For your example you should do something like this, also check the link @Little John posted, that proc is really very useful when working with such a stupid data format
Code: Select all
Structure product_struct
x$
y.i ; or a or b should work too
z.i
EndStructure
Define Temp.product_struct
Define Jshit = LoadJSON(#PB_Any, your_json)
Define tmp = JSONValue(Jshit)
tmp = GetJSONMember(Tmp, "product") ; this gets element next to root level, also assuming you already received key or just know it
ExtractJSONStructure(tmp, Temp, product_struct)
Generally you need first to GetJSONMember (moving to element you need and referencing it by key), then you using returned value to receive specific data by one of functions for this
Re: [probably trivial] Access JSON objects members
Posted: Tue Mar 15, 2016 8:10 am
by bbanelli
Little John wrote:Are you looking for something like
this?
The procedure TraverseJSON() should work for all kinds of dynamic JSON data.
Hi Little John,
yes, thank you! I've managed to adapt your code for some testing purpose. But on a path of Lunasole's statement...
Lunasole wrote:Hah, I understand how you feel trying to do something with this.
I really felt intellectually undercapacitated for not being able to quickly fully grasp logic and motives behind JSON formating...
The stupid is JSON format itself, not a question. I definitely just hate this web-trash, also last time had to work with it a lot too. Even XML is much better.

Well, frankly, so far I've had much more luck with JSON than XML, owing to XML validation, normalization and some other processes that I have to study harder. I am actually adding some REST API code to my current software for communication with web shops, so that's the reason for exploring XML/JSON in the first place...
For your example you should do something like this
/snip
Generally you need first to GetJSONMember (moving to element you need and referencing it by key), then you using returned value to receive specific data by one of functions for this
I've been using freek's code from here:
http://forum.purebasic.com/english/view ... 12&t=62502 and that ExtractJSONStructure().
Is there any reason to believe that approach is suboptimal for any reason whatsoever? I'm basically adding elements to list of structures.
Re: [probably trivial] Access JSON objects members
Posted: Tue Mar 15, 2016 11:10 am
by the.weavster
JSON is a great format
bbanelli wrote:Code: Select all
{
"product": {
"x" : "text",
"y" : false,
"z" : true
}
}
How could you possibly define this object any clearer or easier? XML... bah humbug
If you know the format of the JSON object you're going to receive getting at an element is not difficult in PB. Take your test object above for example, if this was in a string variable named js and you wanted to get the value of x you could do this:
Code: Select all
nJS = JSONValue(ParseJSON(#PB_Any, js))
nProduct = GetJSONMember(nJS,"product")
nX = GetJSONMember(nProduct,"x")
x.s = GetJSONString(nX)
Re: [probably trivial] Access JSON objects members
Posted: Wed Mar 16, 2016 7:54 pm
by Lunasole
bbanelli wrote:I've been using freek's code from here:
http://forum.purebasic.com/english/view ... 12&t=62502 and that ExtractJSONStructure().
Is there any reason to believe that approach is suboptimal for any reason whatsoever? I'm basically adding elements to list of structures.
Well that generator just does what else has to be done manually.
Thanks, nice tool, I didn't seen it before but came to structures too. I don't think there can be any props when using them to extract any values - that definitely makes code much cleaner, shorter and easy to update.
Just in cases when need to extract only several variables from a large JSHT file it might be more rational to extract single variables instead of getting all with structures
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 5:43 am
by vwidmer
How do u get something deeper?
like wind > VWINDBAT - SPEED2
or even deeper?
Code: Select all
{"wind":{"SPEED":"14","TEMP":"27","ANGLE":"66","VWINDBAT":{"ANGLE2":"66","SPEED2":"14","TEMP2":"27"}}}
Thanks
the.weavster wrote:JSON is a great format
bbanelli wrote:Code: Select all
{
"product": {
"x" : "text",
"y" : false,
"z" : true
}
}
How could you possibly define this object any clearer or easier? XML... bah humbug
If you know the format of the JSON object you're going to receive getting at an element is not difficult in PB. Take your test object above for example, if this was in a string variable named js and you wanted to get the value of x you could do this:
Code: Select all
nJS = JSONValue(ParseJSON(#PB_Any, js))
nProduct = GetJSONMember(nJS,"product")
nX = GetJSONMember(nProduct,"x")
x.s = GetJSONString(nX)
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 7:14 am
by infratec
Hi,
try this:
Code: Select all
Structure VWindBatStructure
ANGLE2$
SPEED2$
TEMP2$
EndStructure
Structure WindStructure
SPEED$
TEMP$
ANGLE$
VWINDBAT.VWindBatStructure
EndStructure
Structure AirStructure
wind.WindStructure
EndStructure
Define Air.AirStructure
JSON$ = ~"{\"wind\":{\"SPEED\":\"14\",\"TEMP\":\"27\",\"ANGLE\":\"66\",\"VWINDBAT\":{\"ANGLE2\":\"66\",\"SPEED2\":\"14\",\"TEMP2\":\"27\"}}}"
Debug JSON$
Debug ""
If ParseJSON(0, JSON$)
ExtractJSONStructure(JSONValue(0), @Air, AirStructure)
Debug "Speed2: " + Air\wind\VWINDBAT\SPEED2$
EndIf
Bernd
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 7:39 am
by infratec
For the original question:
Code: Select all
Structure ProductStructure
x$
y.i
z.i
EndStructure
Structure StoreStructure
product.ProductStructure
EndStructure
Define Store.StoreStructure
JSON$ = ~"{\"product\": {\"x\":\"text\",\"y\":false,\"z\":true}}"
Debug JSON$
Debug ""
If ParseJSON(0, JSON$)
ExtractJSONStructure(JSONValue(0), @Store, StoreStructure)
Debug Store\product\x$
Debug Store\product\y
Debug Store\product\z
EndIf
But the JSON is a bit malformed.
PBs ParseJSON() does not like it.
I had to remove the comma after the true.
I don't know if this comma is allowed or not.
If yes, then Fred should improve ParseJSON().
Bernd
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 1:56 pm
by vwidmer
Thanks for the code however I was looking for something a little simpler along these lines
Code: Select all
nJS = JSONValue(ParseJSON(#PB_Any, js))
nProduct = GetJSONMember(nJS,"product")
nX = GetJSONMember(nProduct,"x")
x.s = GetJSONString(nX)
So I dont have to structure the whole json. some of the jsons I have have too much structure to go through all that just to pull one thing unless have to? would be nicer if could just call it blindly but maybe its not possible
Thanks again
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 4:02 pm
by infratec
Hi, hi,
use FindString()
Then you save also a lot of code, because the json lib is not included.
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 4:53 pm
by vwidmer
Well this is what I came up with it does mostly what I was trying to accomplish. It will fail as I dont really know how to put in any kind of error protection yet.
Please improve on it and make changes if you would like and post back.
Thanks
Code: Select all
Global NewMap Result.s()
Procedure gJSValue(jsData.s,jsReq.s)
cnt.i ; counter
jsLVL.i = CountString(jsReq,".")
If Mid(jsReq,Len(jsReq),1) = "."
jsTree.i = 1
Else
jsLVL = jsLVL+1
EndIf
nJS = JSONValue(ParseJSON(#PB_Any, jsData))
If jsLVL > 0
;Debug CountString(jsReq,".")
For cnt = 2 To jsLVL
JSTag.s = StringField(jsReq,cnt,".")
;Debug JSTag
If cnt = 2
;Debug "C1"
nProduct = GetJSONMember(nJS,JSTag)
Else
;Debug "C2"
nProduct = GetJSONMember(nProduct,JSTag)
EndIf
Next
If Mid(jsReq,Len(jsReq),1) = "."
Debug "Get listing for: " + jsReq
;Debug Mid(jsReq,Len(jsReq),1)
If Len(jsReq) = 1
ExtractJSONMap(nJS, Result())
Else
ExtractJSONMap(nProduct, Result())
EndIf
; display the result
ForEach Result()
Debug MapKey(Result()) + " = " + Result()
Next
Else
x.s = GetJSONString(nProduct)
Debug x
EndIf
EndIf
EndProcedure
;js.s = "{"+#DQUOTE$+"product"+#DQUOTE$+":{"+#DQUOTE$+"x"+#DQUOTE$+":"+#DQUOTE$+"text"+#DQUOTE$+","+#DQUOTE$+"y"+#DQUOTE$+":false,"+#DQUOTE$+"z"+#DQUOTE$+":true}}"
js.s = "{"+#DQUOTE$+"status"+#DQUOTE$+":"+#DQUOTE$+"success"+#DQUOTE$+", "+#DQUOTE$+"data"+#DQUOTE$+":{"+#DQUOTE$+"username"+#DQUOTE$+":"+#DQUOTE$+"mycoolusername"+#DQUOTE$+","+#DQUOTE$+"fname"+#DQUOTE$+":"+#DQUOTE$+"V"+#DQUOTE$+","+#DQUOTE$+"lname"+#DQUOTE$+":"+#DQUOTE$+""+#DQUOTE$+","+#DQUOTE$+"sub_id"+#DQUOTE$+":"+#DQUOTE$+"7"+#DQUOTE$+","+#DQUOTE$+"points"+#DQUOTE$+":1,"+#DQUOTE$+"language"+#DQUOTE$+":"+#DQUOTE$+"en"+#DQUOTE$+","+#DQUOTE$+"plan_id"+#DQUOTE$+":1,"+#DQUOTE$+"plan_name"+#DQUOTE$+":"+#DQUOTE$+"Free Plan"+#DQUOTE$+","+#DQUOTE$+"plan_free"+#DQUOTE$+":1,"+#DQUOTE$+"need_account_activation"+#DQUOTE$+":false,"+#DQUOTE$+"need_account_renew"+#DQUOTE$+":false}}"
Debug "Root level:"
gJSValue(js,".")
Debug "1st level:"
gJSValue(js,".data.")
Debug "1st level item:"
gJSValue(js,".data.username")
I was trying to emulate the way ./jq (
https://stedolan.github.io/jq/) program works on the terminal in its simplest form.
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 5:47 pm
by Little John
infratec wrote:But the JSON is a bit malformed.
PBs ParseJSON() does not like it.
I had to remove the comma after the true.
I don't know if this comma is allowed or not.
If yes, then Fred should improve ParseJSON().
This JSON validator says "invalid comma", so ParseJSON() seems to work correct here.
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 6:40 pm
by vwidmer
how to implement code to handle something like this:
Code: Select all
{"positions":[[123,456,"TEST1"],[234,212,"TEST2"],[982,273,"TEST3",]],"time_on_server":null}
Re: [probably trivial] Access JSON objects members
Posted: Wed Jun 28, 2017 7:01 pm
by kenmo
The JSON format is fine (better than XML in some ways), but yes you can request more features in PB's JSON library.
You can try my include file to simplify JSON in PB:
JSON_Helper.pbi
Code: Select all
IncludeFile "JSON_Helper.pbi"
JSON$ = ReplaceString( "{'product': {'x':'text','y':false,'z':true}}" , "'", #DQUOTE$)
ParseJSON(0, JSON$)
Debug JSONStringFromPath( MainJSONObject(0), "product.x") ; shows "text"