Proper way to retrieve nested objects in BRL.Json

Monkey Forums/Monkey Beginners/Proper way to retrieve nested objects in BRL.Json

bitJericho(Posted 2015) [#1]
I have the following code to retrieve nested Json objects. For example:

{
   "status":"ok",
   "count":5,
   "messages":{
      "1":{
         "message_id":"4",
         "author_name":"joe",
         "chat_author":"1",
         "private":0,
         "time":"2015-02-23 01:33:44",
         "message":"Hello World"
      },
      "2":{
         "message_id":"5",
         "author_name":"joe",
         "chat_author":"1",
         "private":0,
         "time":"2015-02-23 01:33:49",
         "message":"Hello World"
      },
      "3":{
         "message_id":"6",
         "author_name":"joe",
         "chat_author":"1",
         "private":0,
         "time":"2015-02-23 01:33:54",
         "message":"Hello World"
      },
      "4":{
         "message_id":"7",
         "author_name":"joe",
         "chat_author":"1",
         "private":0,
         "time":"2015-02-23 01:34:09",
         "message":"Hello World"
      },
      "5":{
         "message_id":"8",
         "author_name":"joe",
         "chat_author":"1",
         "private":0,
         "time":"2015-02-23 01:34:10",
         "message":"Hello World"
      }
   }
}



Here is the relavent code I use to get the author's name in the first entry. You'll see I have to create 3 JsonObjects before I can get to where I'm going, and there's some string to json and back conversion going on. Is this how it's intended to be used or am I missing something? I realize an array inside the json object would be better but the server I'm using doesn't really support that for some silly reason.


	Method ProcessUpdate()
		Self.currentUpdates = New JsonObject(getUpdate.ResponseText())
		
		If Self.currentUpdates.GetInt("count", 0 ) > 0
			Local messagesArray := JsonObject(JsonObject(Self.currentUpdates.Get("messages").ToJson()).Get("1").ToJson()).GetString("author_name")
			Print messagesArray
		Endif
	End



Nobuyuki(Posted 2015) [#2]
casting is something you gotta do with brl.json 'cause it doesn't make assumptions about the type of value you're fetching with Get() since it can be either a JsonArray or a JsonObject. I'm assuming it was done this way because the code is based on an earlier community json lib that did basically the same thing, but I don't know for sure. Either way, you can make helper methods to assist you with making the syntax for method chaining a bit more readable. Presuming you need more data from the parent object, however, this type of deep message plucking isn't really the best way to go about it -- you're better off grabbing the objects up to the level where you need to access most of the data using method chaining, then for the rest, use nested code blocks or something.

In any case, no conversion to/from strings is necessary until the final method where you pluck the actual string value from the object you need:
			Local messagesArray := JsonObject(JsonObject(currentUpdates.Get("messages")).Get("1")).GetString("author_name") 



muddy_shoes(Posted 2015) [#3]
While it's possible Mark referenced my JSON lib, the need to be explicit about whether you're expecting a JSONObject or a JSONArray is kind of required as they have different access mechanisms. You could just create a single JSONThing that supports both types. You'd end up with error trapping based on type internally anyway but maybe the convenience factor would be worth it for some people. In general though the expectation is that you'd parse out a JSON file into another data structure which would support the kind of queries you want to make.

FWIW, in my lib there are optional calls to tidy up the casts and brackets for this sort of thing. The code would look more like:

	Local authorName:String = currrentUpdates.GetItem("messages").AsJSONObject().GetItem("1").AsJSONObject().GetItem("author_name")		


Whether that's better or good enough is a matter of opinion.