About JsonObject to Native Interface in Cocoa/Java

Is there a JsonObject native mapped type in Cocoa/Java?
I mean supposed that I create methods like:

     /**
	 * Map json string to object
	 */
	public func map(jsonString:String!) ->() {
		let myObject:Sugar.Json.JsonObject = Sugar.Json.JsonObject.Load( jsonString );
		if let obj = myObject {
			let allKeys = obj.Keys;
			for key in allKeys {
				if let value = obj.Item[key] {
				   // do something here...	
				}
			}
			self.rawObject=Sugar.Json.JsonObject.Load( myObject.ToJson() );
		}
	}

where I have

/**
* Base JSON Object Model
*/
public class BaseObject {
	
	private var rawObject:Sugar.Json.JsonObject?;
	
	public init() {
		super.init();
	}

and I would like to return this whole self.rawObject as a native JSON object (Cocoa/Java) to the caller, is there any public interface api (the ones mapped in https://github.com/remobjects/sugar/blob/master/Sugar/JSON/JsonObject.pas) to get back a native object in Cocoa so Swift.Dictionary (so using native json parsers objects) like:

        let epoch:NSTimeInterval = NSDate().timeIntervalSince1970;
         let jsonObject : [String:AnyObject] = [
            "timestamp" : epoch
        ];
        print("\(jsonObject["timestamp"])");

in order that I could both do NSJSONSerialization like:

do {
            let data:NSData =  try NSJSONSerialization.dataWithJSONObject(jsonObject, options: NSJSONWritingOptions.PrettyPrinted);
            print("\(data)");
            
            let jsonObj2:AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments);
            print("\(jsonObj2)");
            
        } catch _ {
        
        }

and the same for Java/Android.

I have tried to use a mapping method like

    /**
	 * Get Json Object
	 */
	public func toJsonObject() -> ([String:AnyObject]?) {
		var json:[String:AnyObject] = [String:AnyObject]();
		if let obj = self.rawObject {
			let allKeys = obj.Keys;
			for key in allKeys {
				if let value = obj.Item[key] {
					json[key]=value;
				}
			}
			return json;
		}
		return nil;
	}

to map the Sugar.JSON.JsonObject into a Swift.Dictionary like structure in order to back a json like the following:

{
  "artists": {
    "href": "https:\/\/api.spotify.com\/v1\/search?query=tania+bowra&offset=0&limit=20&type=artist",
    "items": [
      {
        "images": [
          {
            "url": "https:\/\/i.scdn.co\/image\/f2798ddab0c7b76dc2d270b65c4f67ddef7f6718",
            "width": 640,
            "height": 640
          }
        ]
        "href": "https:\/\/api.spotify.com\/v1\/artists\/08td7MxkoHQkXnWAYD8d6Q",
        "type": "artist",
        "name": "Tania Bowra",
        "uri": "spotify:artist:08td7MxkoHQkXnWAYD8d6Q"
      }
    ]
  }
}

in order now to do something like

if let jsonObject=result.toJsonObject() { // json object
                    print("\(jsonObject)\n\(jsonObject["artists"])");
                    if let jsonValue=jsonObject["artists"] {
                        print("\(jsonValue["href"])");
                    }
                }

but I’m only traversing the first nodes/root level, since at second level ( i.e. [‘artists’]) I get a Sugar.JsonValue when doing let value = obj.Item[key]. and so only one level is returned as a Swift json object:

print("\(jsonObject)\n\(jsonObject["artists"])");

but not inners levels like jsonObject["artists"]!["href"]

@mh Looking at the JSONObject.pas I can see that

Items: Dictionary<String, JsonNode> := new Dictionary<String, JsonNode>;

is private. Now supposed it would be public I could access to Sugar.Dictionary there. And since a Sugar.Dictionary is a mapped type. I could use it as-it-is in Cocoa, right?

Thank you.

i’m not sure what you mean. JsonObject is a native Cocoa class (on Cocoa). It’s also not mapped to anything.

So If I pass a Sugar.JsonObject to Cocoa (non RTL):

do {
                        let data:NSData =  try NSJSONSerialization.dataWithJSONObject(jsonObject, options: NSJSONWritingOptions.PrettyPrinted);
                        print("\(data)");
          
                    } catch _ { }

This will return me with an error:

Optional(Invalid type in JSON write (JsonObject))

Well, you wanna use Sugar.Json or NSJSONSerialization? Why both?

Since I would like to have an accessor like

print("\(jsonObject["timestamp"]) - \(jsonObject["item"]!["name"])");

i.e.

jsonObject['root']['level1'] in a Swift json object declared as usual:

let jsonObject : [String:AnyObject] = [
            "timestamp" : epoch,
            "item" : [
                "name" : "track"
            ]
        ];

So if I were able to expose a Swift.Dictionary of the Sugar.Json object I could have the [] accessor like in ordinary Swift code.

I see. i suppose the Sugar.Json API just could use some improving to make that possible w/o having to cast. right now, jsonObject["item"] is a JsonNode, not a JsonObject, so you cant directly access the sub-properties. i’ll think about this some more.

1 Like

@mh Yes exactly, having a jsonObject["item"] like a JsonObject will definitively solve the problem, since one could traverse each object through the Keys (if any) and then map into a dictionary.
Thank you.

Check the latest sugar in GitHub, develop branch. Does that look better?

Do you refer to commit https://github.com/remobjects/sugar/commit/5be98d022d9b3a74dafa5d21093a86da53344d88 ?

Correct.

Ok thank you. I’m trying to use the new override you have added to make a recursive access to the JsonValue / JsonNode then.

1 Like