JSON to "php/js-like" variable?

Just starting out? Need help? Post your questions and find answers here.
destiny
User
User
Posts: 29
Joined: Wed Jul 15, 2015 12:58 pm
Location: CCCP

JSON to "php/js-like" variable?

Post by destiny »

Hi guys!
Is there any chance to convert input json string (with dynamic data - such as any names of variables and any number of this variables, mixed with arrays with same properties - any number of variableth with any names) and objects containing such things?
This variable must be like php variables with associative names or something like this to easy acces to any part of that variable? Is this possible? I'm breaking my head more than a week to understand how to do this and i'm at the beginning every time.

Just for example, two json strings that can come (it's only examples, incoming json strings can be any mix of arrays/objects/data and i formatted it to easy reading with crlf's/spaces):
JSON example #1 (object with array with numbers/string/arrays[/objects])

Code: Select all

[
  {
    "var1_name": value1_flo_or_int,
    "var2_name": "some string",
    "var3_named_array": {
      "arrvar1": value_arrvar1_flo_or_int,
      "arrvar2": "string"
      },
    "var4_name": value4_flo_or_int
  }
]
JSON example #2 (array with numbers, strings, arrays[/objects] etc)

Code: Select all

  {
    "var1_named_array": {
      "arrvar1": value_arrvar1_flo_or_int,
      "arrvar2": "string"
      },
    "var2_name": "some string",
    "var3_name": value3_flo_or_int,
    "var4_named_array": {
      "arrvar1": value_arrvar1_flo_or_int,
      "arrvar2": value_arrvar2_flo_or_int,
      "arrvar3": "string"
      },
    "var5_name": value5_flo_or_int
  }
And i want at the end some variable that i can access like
for JSON input #1
debug "'" + json_decoded_var\var2_name + "'" ; will be 'some string'
debug "'" + json_decoded_var\var3_named_array('arrvar1') + "'" ; will be 'value_arrvar1_flo_or_int'

Or maybe "json_decoded_var.var3_named_array.arrvar1" to access. Just named access, how it will be done - by "\" like structure or by "." - it does not matter.
And i think it's important that variables inside variables can be sorted.

I tried to make Structured object with procedure that recursively calls itself when inner variable is object or array without any luch. I'm still novice in pb and can't understand some things and just stuck in a simple or maybe little moderate question.
In php it's simple as we breathe. In pb i can't understand how to do this. :(
Please, help me understand it and finish it. I want to learn pb, but stuck. "Just lost in the three pines".

At the end i want to do #1 or #2

Code: Select all

ParseResult = ParseJSON(0, InputString$)
If ParseResullt
  ParseValue = JSONValue(0)
  ParseResult = ProcedureThatConvertsJSONStringToVariable(ParseValue, myNewVariableWithParsedJSON)
  ;ParseResult is the 1 = success or 0 = fail
ElseIf
  ; error in parsing
End

Code: Select all

ParseResult = ParseJSON(0, InputString$)
If ParseResullt
  ParseValue = JSONValue(0)
  myNewVariableWithParsedJSON = ProcedureThatConvertsJSONStringToVariable(ParseValue)
  ;myNewVariableWithParsedJSON - just a result of converting input json string to variable
ElseIf
  ; error in parsing
End
Last edited by destiny on Wed Jul 15, 2015 6:42 pm, edited 1 time in total.
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: JSON to variable?

Post by said »

destiny
User
User
Posts: 29
Joined: Wed Jul 15, 2015 12:58 pm
Location: CCCP

Re: JSON to variable?

Post by destiny »

I've seen this thread. This generator makes hardcoded structures. When input json string changes then code that uses hardcoded structures will not work.
User avatar
falsam
Enthusiast
Enthusiast
Posts: 632
Joined: Wed Sep 21, 2011 9:11 am
Location: France
Contact:

Re: JSON to variable?

Post by falsam »

First of all, welcome :)

Sorry but json with dynamic data it is rather strange to me.

I wonder if I will not be off topic. Maybe your JSON file are on a dedicated server? I coded an include to receive data generated by php file.
HTTPRequest.pbi

Code: Select all

;HTTPRequest() Version 1.00
;Contributor Falsam & CO
;Create 08 September 2014
;Update 08 September 2014
:

Procedure.s HTTPRequest(HostName.s, HostFolder.s, HostPort, PhpScript.s, Method.s="GET", DataSend.s="", *CallBackError=0, Mode=#PB_Network_TCP)
  Protected HostConnection.i=0
  Protected HostUrl.s
  Protected dwBytes, *Buffer, Buffer.s
  
  If InitNetwork()
   HostConnection = OpenNetworkConnection(HostName, HostPort, Mode)
   
   If HostConnection
     HostUrl = Method+" "
     HostUrl + HostFolder + PhpScript
     
     If DataSend<>""
       HostUrl+"?"+DataSend
     EndIf  
     
     HostUrl + " HTTP/1.0" + #CRLF$ + "Host: " + HostName + #CRLF$ + #CRLF$ + "Connection: Close" 
    
     If SendNetworkString(HostConnection, HostUrl, #PB_UTF8)
       Delay(200)
       *buffer = AllocateMemory(65535)
       dwBytes = 1
       While dwBytes > 0
         dwBytes = ReceiveNetworkData(HostConnection, *buffer, 65535)
       Wend
     Else
       If *CallBackError <> 0
         CallFunctionFast(*CallBackError, 3) ;Error SendNetworkString()
       Else
         ProcedureReturn "Error"
       EndIf
     EndIf
   
     CloseNetworkConnection(HostConnection)
     
     Buffer = PeekS(*Buffer)
     FreeMemory(*Buffer)

     ProcedureReturn StringField(Buffer, CountString(Buffer, #CRLF$) + 1, #CRLF$)     
     
   Else
     If *CallBackError <> 0
       CallFunctionFast(*CallBackError, 2) ;Server connection error
     Else
       ProcedureReturn "Error"
     EndIf
   EndIf  
Else 
   If *CallBackError <> 0
     CallFunctionFast(*CallBackError, 1) ;InitNetwork() Error
   Else
     ProcedureReturn "Error"
   EndIf
EndIf
EndProcedure
First code demo

Code: Select all

;Receive Php Arrays
IncludeFile "HTTPRequest.pbi"

Enumeration
  #Json
EndEnumeration

Global Buffer.s, i
Global Dim Result.s(0)

Buffer = HTTPRequest("s242132022.onlinehome.fr", "/racal/", 80, "test0.php")

Debug "Control Php Array : " + Buffer

If ParseJSON(#Json, Buffer)
  ;Transfer the php array to an array
  ExtractJSONArray(JSONValue(#Json), Result())
    
  ;Display the result
  For i=0 To ArraySize(Result())
    Debug Result(i)
  Next
EndIf
Second code demo

Code: Select all

;Receive Php Associative Arrays
IncludeFile "HTTPRequest.pbi"

Enumeration
  #Json
EndEnumeration

Global Buffer.s
Global NewMap Result.s()

Buffer = HTTPRequest("s242132022.onlinehome.fr", "/racal/", 80, "test1.php", "GET", "")

Debug "Control Php Associative Arrays : " + Buffer

If ParseJSON(#Json, Buffer)
    ; transfer the php array to a map
    ExtractJSONMap(JSONValue(#Json), Result())
  
    ; display the result
    ForEach Result()
      Debug MapKey(Result()) + " = " + Result()
    Next
EndIf

➽ Windows 11 64-bit - PB 6.21 x64 - AMD Ryzen 7 - NVIDIA GeForce GTX 1650 Ti

Sorry for my bad english and the Dunning–Kruger effect 🤪
PMV
Enthusiast
Enthusiast
Posts: 727
Joined: Sat Feb 24, 2007 3:15 pm
Location: Germany

Re: JSON to variable?

Post by PMV »

If the pb implementation doesn't fit you, maybe this include does.
http://www.purebasic.fr/english/viewtop ... 12&t=45348

MFG PMV
destiny
User
User
Posts: 29
Joined: Wed Jul 15, 2015 12:58 pm
Location: CCCP

Re: JSON to variable?

Post by destiny »

falsam wrote:Sorry but json with dynamic data it is rather strange to me.

I wonder if I will not be off topic. Maybe your JSON file are on a dedicated server? I coded an include to receive data generated by php file.
Thanx, but no, this is other things.
I don't need to connect to anything.
I have working code to communicate between "server" side and "client side".
Yes, i have dynamic data incoming.

Ok. I'll try to explain little more.

* First, i have aggregation server/laboratory that recieves data from stations.
* At each station there are [1..nn] probes.
* Each probe has it's own group of sensors and each probe sends it's data when it's time to send. Probe sends only part of all information it have.
That's why probe json can be

{ "name": "probe 12", "temp": 12.6, "velocity": 5.5 }
{"name": "probe 6", "temp": {
0: 12.8, 1: 12.7, 2: 12.7, 3: 12.5
}
}
{"name": "probe 7", "pressure": 1.112}

or other combinations.
Any of the probes can be offline and at the any of the moment there can be new probes. So if probe is offline or there are no probes = i don't need a variable that will have data for offline probes.

* There are [1..nn] stations. Each of them can or can not send aggregated info for this probes. I can recieve other structured json:
{
"station 3": {
{ "name": "probe 12", "temp": 12.6, "velocity": 5.5 },
{"name": "probe 7", "pressure": 1.112}
}
}

* There are aggregation center, that can send updated data (that's why data is compact and DYNAMIC) for only changed probes/stations/etc (now this data is object, not an array):
[{
"stations": {
"station 2": {
{ "name": "probe 12", "temp": 12.6, "velocity": 5.5 }
},
"station 3": {
{ "name": "probe 12", "temp": 12.6, "velocity": 5.5 },
{"name": "probe 7", "pressure": 1.112}
}
"station 7": {
"probes": {
{"name": "probe 12", "temp": 12.6, "velocity": 5.5 },
{"name": "probe 7", "pressure": 1.112}
},
"sensors": {"humidity": 99.256, "temp": 28.1},
"analyzers": {
"1": "offline",
"2": "online",
"3": 1,
"4": 0
}
}
}]

"Client" can connect to server and recieve server json. Can connect to any station and recieve station's jsons. Can connect to any probe and recieve probe's jsons. Etc.

Probe can send many of other parameters, and part of probes has it's own sensors that other probes havent etc.
So if i hardcode all possible data from probes/stations/servers it will be very complex, massive and it will not work if any of the probes will be updated and will be upgraded with new, unknown sensor for the program. This will result in need of rewriting code of the program, recompile, stop/start etc. It can't be done. So i need to write versatile code that will work with any incoming json data.
destiny
User
User
Posts: 29
Joined: Wed Jul 15, 2015 12:58 pm
Location: CCCP

Re: JSON to variable?

Post by destiny »

PMV wrote:If the pb implementation doesn't fit you, maybe this include does.
http://www.purebasic.fr/english/viewtop ... 12&t=45348

MFG PMV
Thanx, i read and studied your code your code earlier, a month ago.
Your implementation are close enough to what i need, but far enough too.
I need to sort data inside variable that will have json decoded information, i need to cycle through data that in there and few other little things.
And you use your own decoding procedures, but pb 5.31 is able to decode json, so it will need much less code to implement it?

If we create a universal/versatile code then other people who will be in need of decoding any json strings with recent versions of pb and with php-like access to json data in result variable - then it will make pb more friendly and it will help save a lot of time to other coders :)
Little John
Addict
Addict
Posts: 4779
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: JSON to variable?

Post by Little John »

You have to traverse the JSON data recursively:

Code: Select all

; PB 5.31

EnableExplicit

Procedure TraverseJSON (v.i)
   Protected.i i, last, jn
   
   Select JSONType(v)
      Case #PB_JSON_Null
         Debug "null"
         
      Case #PB_JSON_String
         Debug "string = '" + GetJSONString(v) + "'"
         
      Case #PB_JSON_Number
         Debug "number = " + GetJSONDouble(v)
         
      Case #PB_JSON_Boolean
         Debug "boolean = " + GetJSONBoolean(v)
         
      Case #PB_JSON_Array
         Debug "-- array"
         last = JSONArraySize(v) - 1
         For i = 0 To last
            jn = GetJSONElement(v, i)
            TraverseJSON(jn)
         Next   
         
      Case #PB_JSON_Object
         Debug "-- object"
         If ExamineJSONMembers(v)
            While NextJSONMember(v)
               Debug JSONMemberKey(v) + ":"
               jn = JSONMemberValue(v)
               TraverseJSON(jn)
            Wend
         EndIf
   EndSelect
EndProcedure


; -- Demo
Define jn.i, input$

jn = ParseJSON(#PB_Any, "null")
TraverseJSON(JSONValue(jn))
Debug ""

jn = ParseJSON(#PB_Any, #DQUOTE$ + "Hello" + #DQUOTE$)
TraverseJSON(JSONValue(jn))
Debug ""

jn = ParseJSON(#PB_Any, "2.7")
TraverseJSON(JSONValue(jn))
Debug ""

jn = ParseJSON(#PB_Any, "true")
TraverseJSON(JSONValue(jn))
Debug ""

jn = ParseJSON(#PB_Any, "[[1, 2], [3, 4], [5, 6]]")
TraverseJSON(JSONValue(jn))
Debug ""

input$ = "{ " + #DQUOTE$ + "x" + #DQUOTE$ + ": 10, " + 
         #DQUOTE$ + "y" + #DQUOTE$ + ": 20, " + 
         #DQUOTE$ + "z" + #DQUOTE$ + ": 30 }"
jn = ParseJSON(#PB_Any, input$)
TraverseJSON(JSONValue(jn))
destiny
User
User
Posts: 29
Joined: Wed Jul 15, 2015 12:58 pm
Location: CCCP

Re: JSON to variable?

Post by destiny »

Little John wrote:You have to traverse the JSON data recursively:
Oh, yes, i forgot to say it. I can successfully debug any data i recieve. But i can't put it to "one big" variable.
Little John
Addict
Addict
Posts: 4779
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: JSON to variable?

Post by Little John »

destiny wrote:Oh, yes, i forgot to say it. I can successfully debug any data i recieve. But i can't put it to "one big" variable.
The JSON string that you receive is one big variable. ;-)

So you want to store the same data in a different format?
You can use my above procedure TraverseJSON() for splitting the received JSON string into its smallest parts.
And then, instead of "Debug", use other commands as you want for putting all the parts again together in another format.
destiny
User
User
Posts: 29
Joined: Wed Jul 15, 2015 12:58 pm
Location: CCCP

Re: JSON to variable?

Post by destiny »

Little John, yes, with php-like access. It's very very comfortable and easy to use. I think it's the best type of access ever.
English is not my native language, so i'll think more how to explain what i want if it's not understandable with my prev posts.

This implementation is very close http://www.purebasic.fr/english/viewtop ... 12&t=60656
And Derren had the same question i have, as i see, and he not finished it.
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: JSON to "php/js-like" variable?

Post by Lunasole »

@Little John, thanks, your code saved me some time as I wanted to read some json file without learning that messing format itself ^^
Also I've slightly modified it to receive more formatted and structured result

Code: Select all

; traverse jsht tree and prints data about all elements
; v	:	the result of JSONValue()
; RETURN: none
Procedure jShtDebug (v.i)
	Protected.i i, last
	Static.i	Deepth, TrueDeepth, Res$	
	If Not TrueDeepth
		Macro TjsFmt: LSet(#NULL$, Deepth * 4, " ") : EndMacro
		Res$ = "[[ JSHTON " + Str(v) + " ]]" + #CRLF$
	EndIf:	TrueDeepth + 1
	
	Select JSONType(v)
		Case #PB_JSON_Null
			Res$ + TjsFmt + "[ NUL ]" + #CRLF$
			
		Case #PB_JSON_String
			Res$ + #DOUBLEQUOTE$ + GetJSONString(v) + #DOUBLEQUOTE$ + #CRLF$
			
		Case #PB_JSON_Number
			Res$ + GetJSONDouble(v) + #CRLF$
			
		Case #PB_JSON_Boolean
			Res$ + GetJSONBoolean(v) + "b" + #CRLF$
			
		Case #PB_JSON_Array
			Res$ + "/[ ARR ]" + #CRLF$
			last = JSONArraySize(v) - 1
			Deepth + 1
			For i = 0 To last
				jShtDebug(GetJSONElement(v, i))
			Next
			Deepth - 1
			
		Case #PB_JSON_Object
			Res$ + TjsFmt + "[ OBJ ]\" + #CRLF$
			Deepth + 1
			If ExamineJSONMembers(v)
				Deepth + 1
				While NextJSONMember(v)
					Res$ + TjsFmt + JSONMemberKey(v) + " = "
					jShtDebug(JSONMemberValue(v))
				Wend
				Deepth - 1
			EndIf
			Deepth - 1
	EndSelect
	
	TrueDeepth - 1
	If Not TrueDeepth
		UndefineMacro TjsFmt : 	Res$ + "[[ ENDJSHT " + Str(v) + " ]]"
		Debug Res$
	EndIf
EndProcedure
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
Post Reply