How to create JSON format from Realm "Results" using Object Mapper - json

I try to create JSON format from Realm Results using Object Mapper. So, I created two generic methods to do that. Fisrt method create array form Results and looks like that:
var allRealmData: Results<Project>? // in this variable I save all Project Objects first
func makeAnArrayFromResults<T>(object: T.Type) -> [T]?{
var array = [T]()
guard let mainArray = allRealmData else { return nil }
for i in mainArray {
if let object = i as? T {
array.append(object)
}
}
return array
}
then I would like to use Object Mapper to change this array to JSON Object, but when I try do it, I receive an error and don't know how can I resolve it. My second method looks like that:
func createJSON<T: Object>(object: T.Type){
let array = makeAnArrayFromResults(object)
let json = Mapper().toJSONString(array!, prettyPrint: true) //here error
}
error info: Cannot invoke "toJSONString" with an argument list of type"([T], prettyPrint: Bool)".
Do you have any sugestions how can I create JSON from Result in Realm?

Firstly, makeAnArrayFromResults<T> is really just map:
let someRealmResults: Results<Project>?
...
let array = someRealmResults?.map { $0 } // => [Project]?
As far as the Object Mapper integration goes, it looks like you don't have a toJSONString function defined that satisfies the first argument type constraints of [Person].
There's quite a bit of discussion in Object Mapper's issue tracker about interoperability with Realm that you may find useful: https://github.com/Hearst-DD/ObjectMapper/issues/475

Related

How to iterate a list inside of a JSON object using Kotlin

I am receiving a JSON object from an HTTP request using the Fuel library that looks like:
{
'items': ['item1', 'item2', 'item3']
}
My code for getting the JSONobject is:
Fuel.get("get_cameras").responseJson { request, response, result ->
var my_json = result.get().obj()
}
How can I iterate over the 'items' key? I have tried:
for (items in my_json) {}
but it says it doesn't have an iterator() method. I am coming from Python and am probably thinking about this in the wrong way because I see plenty of other seemingly similar questions but none seem to be related to what I am trying to do.
You need to first get a hold of the array nested in your object with the "items" key, and then you can iterate over that array. The basic way to do this (if you're sure that it only contains strings) would be to loop over its indexes and call getString on the array for each index:
val my_json = result.get().obj()
val items = my_json.getJSONArray("items")
for (i in 0 until items.length()) {
val item = items.getString(i)
// use item
}
If you don't want to deal with indexes while iterating, you could wrap the iteration of a JSONArray into an extension function:
fun JSONArray.forEachString(action: (String) -> Unit) {
for (i in 0 until length()) {
action(getString(i))
}
}
Which could then be used like this:
val items = my_json.getJSONArray("items")
items.forEachString { item ->
// use item
}
You could extend the JSONArray class with an iterator function as well if you really wanted to iterate the array with a regular for loop, but it would be more trouble than it's worth.

Parse Json Response through Dictionary object

I have Json response through Facebook API like this:
Now I want to parse this data so I can use within my game. For this purpose, I have written code up to this:
public void OnChallengesButtonClick ()
{
SoundManager.Instance.PlayButtonClickSound ();
FB.API ("/me/friends", HttpMethod.GET, RetrieveFacebookFriends);
}
public void RetrieveFacebookFriends (IGraphResult result)
{
if (!string.IsNullOrEmpty (result.Error)) {
Debug.Log ("ERROR: " + result.Error);
return;
}
IDictionary<string,object> friendsDict = result.ResultDictionary;
Debug.Log ("raw: " + result.RawResult);
}
So how to extract name and ID data from available Json response through Dictionary object?
Basically you should create a class to serialize/deserialize an object:
class FBResponse
FBDataResponse data;
class FBDataResponse
string name;
string id;
Take a look to my response here for more details (after "Final EDIT" part):
Converting arrays of arrays to json
It should be easy to create those two class and use them to deserialize the FB response. Just remember that your variables will need to match the same name with the json response from Facebook (for example you cannot call data data1).
After you have the object it should be easy to do what you want with it... and with the object you should be able to get the json again.
PS. Unity default json serializer does not support Dictionary that's why you need to serialize two object. If you don't want that you should try to use a different library.
I think this is all I need: JSON with Unity
friends = (List<object>)(((Dictionary<string, object>)friendsH) ["data"]);
if(friends.Count > 0) {
var friendDict = ((Dictionary<string,object>)(friends[0]));
var friend = new Dictionary<string, string>();
friend["id"] = (string)friendDict["id"];
friend["first_name"] = (string)friendDict["first_name"];
}
Before I can't able to find this post from Facebook.

Nested Arrays throwing error in realm.create(value: JSON) for Swift

I'm using Realm in my Swift project and have a rather long JSON file with a couple of nested properties. I'm aware that in order for Realm to use this serialized JSON data directly, the properties need to match exactly (https://realm.io/docs/swift/latest/#json).
But because Realm Lists need to have an Object instead of a String, I have to use something like List with Requirement being a Realm Object that holds a single String called 'value'.
When I run this code:
try! realm.write {
let json = try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())
let exhibit = Exhibit(value: json)
exhibit.id = "1"
realm.add(exhibit, update: true)
}
I get this error message:
*** Terminating app due to uncaught exception 'RLMException', reason: 'req1' to initialize object of type 'Requirements': missing key 'value''
Here's a shortened version of the JSON I'm feeding in there:
{
"exhibit_name": "test1",
"requirements": [
"req1",
"req2"
],
"geofence": {
"latitude": 36.40599779999999,
"longitude": -105.57696279999999,
"radius": 500
}
}
And my Realm model classes are this:
class Exhibit: Object {
override static func primaryKey() -> String? {
return "id"
}
dynamic var id = "0" //primary key
dynamic var exhibit_name: String = ""
let requirements = List<Requirements>()
dynamic var geofence: Geofence?
}
class Geofence: Object {
dynamic var latitude: Float = 0.0
dynamic var longitude: Float = 0.0
dynamic var radius: Float = 0.0
}
class Requirements: Object {
dynamic var value = ""
}
I find it interesting that I'm not getting any errors for the Geofence property, since that's a dictionary.
How do I set up the Requirements model to make this work properly?
Unfortunately you can't just setup your Requirements model in a different way, which would allow you to directly map your JSON to Realm objects.
The init(value: AnyObject) initializer expects either a dictionary, where the keys are the names of your object properties, or an array, where the property values are ordered in the same like they are defined in your object model. This initializer is recursively called for related objects.
So to make that work, you will need to transform your JSON, so that you nest the string values into either dictionaries or arrays. In your specific case you could achieve that like seen below:
…
var jsonDict = json as! [String : AnyObject]
jsonDict["requirements"] = jsonDict["requirements"].map { ["value": $0] }
let exhibit = Exhibit(value: jsonDict)
…
Side Note
I'd recommend using singular names for your Realm model object classes (here Requirement instead Requirements) as each object just represent a single entity, even if you use them only in to-many relationships.

Safe Dynamic JSON Casts In Swift

I suspect that I am not quite grokking Swift 1.2, and I need to RTFM a bit more.
I'm working on a Swift app that reads JSON data from a URI.
If the JSON data is bad, or nonexistent, no issue. The JSON object never instantiates.
However, if the JSON data is good JSON, but not what I want, the object instantiates, but contains a structure that is not what I'm looking for, I get a runtime error.
I looked at using Swift's "RTTI" (dynamicType), but that always returns "<Swift.AnyObject>", no matter what the data is.
I want the JSON to be a specific format: An array of Dictionaries:
[[String:String]]! JSON: [{"key":"value"},{"key","value"},{"Key":"value"}]
If I feed it a single element:
{"Key":"value"}
The routine I have tries to cast it, and that fails.
I want to test the JSON object to make sure that it has a structure I want before casting.
if(nil != inData) {
let rawJSONObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(inData, options: nil, error: nil)
println("Type:\(rawJSONObject.dynamicType)")
if(nil != rawJSONObject) {
// THE LINE BELOW BLOWS UP IF I FEED IT "BAD/GOOD" JSON:
let jsonObject: [[String:String]]! = rawJSONObject as! [[String:String]]!
// I NEED TO TEST IT BEFORE DOING THE CAST
if((nil != jsonObject) && (0 < jsonObject.count)) {
let jsonDictionary: [String:String] = jsonObject[0]
if("1" == jsonDictionary["semanticAdmin"]) { // We have to have the semantic admin flag set.
let testString: String! = jsonDictionary["versionInt"]
if(nil != testString) {
let version = testString.toInt()
if(version >= self.s_minServerVersion) { // Has to be a valid version for us to pay attention.
self.serverVersionAsInt = version!
}
}
}
}
}
}
My question is, is there a good way to test an NSJSONSerialization response for the structure of the JSON before uwinding/casting it?
I feel as if this question may be closer to what I need, but I am having trouble "casting" it to my current issue.
You can use safe unwrapping to test the type of your raw object, for example:
if let jsonObject = rawJSONObject as? [[String:String]] {
// jsonObject is an array of dictionaries
} else if let jsonObject = rawJSONObject as? [String:String] {
// jsonObject is a dictionary
// you can conform it as you wish, for example put it in an array
} else {
// fail, rawJSONObject is of another type
}
Currently, your code crashes because of the forced unwrapping, with !, of values that will be nil if the cast fails.

Grails: Easy and efficient way to parse JSON from a Request

Please pardon me if this is a repeat question. I have been through some of the questions/answers with a similar requirement but somehow got a bit overwhelmed and confused at the same time. My requirement is:
I get a JSON string/object as a request parameter. ( eg: params.timesheetJSON )
I then have to parse/iterate through it.
Here is the JSON that my grails controller will be receiving:
{
"loginName":"user1",
"timesheetList":
[
{
"periodBegin":"2014/10/12",
"periodEnd":"2014/10/18",
"timesheetRows":[
{
"task":"Cleaning",
"description":"cleaning description",
"paycode":"payCode1"
},
{
"task":"painting",
"activityDescription":"painting description",
"paycode":"payCode2"
}
]
}
],
"overallStatus":"SUCCESS"
}
Questions:
How can I retrieve the whole JSON string from the request? Does request.JSON be fine here? If so, will request.JSON.timesheetJSON yield me the actual JSON that I want as a JSONObject?
What is the best way to parse through the JSON object that I got from the request? Is it grails.converters.JSON? Or is there any other easy way of parsing through? Like some API which will return the JSON as a collection of objects by automatically taking care of parsing. Or is programatically parsing through the JSON object the only way?
Like I said, please pardon me if the question is sounding vague. Any good references JSON parsing with grails might also be helpful here.
Edit: There's a change in the way I get the JSON string now. I get the JSON string as a request paramter.
String saveJSON // This holds the above JSON string.
def jsonObject = grails.converters.JSON.parse(saveJSON) // No problem here. Returns a JSONObject. I checked the class type.
def jsonArray = jsonArray.timesheetList // No problem here. Returns a JSONArray. I checked the class type.
println "*** Size of jsonArray1: " + jsonArray1.size() // Returns size 1. It seemed fine as the above JSON string had only one timesheet in timesheetList
def object1 = jsonArray[1] // This throws the JSONException, JSONArray[1] not found. I tried jsonArray.getJSONObject(1) and that throws the same exception.
Basically, I am looking to seamlessly iterate through the JSON string now.
I have wrote some code that explains how this can be done, that you can see below, but to be clear, first the answers to your questions:
Your JSON String as you wrote above will be the contents of your POST payload to the rest controller. Grails will use its data binding mechanism to bind the incomming data to a Command object that your should prepare. It has to have fields corresponding to the parameters in your JSON String (see below). After you bind your command object to your actual domain object, you can get all the data you want, by simply operating on fields and lists
The way to parse thru the JSON object is shown in my example below. The incomming request is esentially a nested map, with can be simply accessed with a dot
Now some code that illustrates how to do it.
In your controller create a method that accepts "YourCommand" object as input parameter:
def yourRestServiceMethod (YourCommand comm){
YourClass yourClass = new YourClass()
comm.bindTo(yourClass)
// do something with yourClass
// println yourClass.timeSheetList
}
The command looks like this:
class YourCommand {
String loginName
List<Map> timesheetList = []
String overallStatus
void bindTo(YourClass yourClass){
yourClass.loginName=loginName
yourClass.overallStatus=overallStatus
timesheetList.each { sheet ->
TimeSheet timeSheet = new TimeSheet()
timeSheet.periodBegin = sheet.periodBegin
timeSheet.periodEnd = sheet.periodEnd
sheet.timesheetRows.each { row ->
TimeSheetRow timeSheetRow = new TimeSheetRow()
timeSheetRow.task = row.task
timeSheetRow.description = row.description
timeSheetRow.paycode = row.paycode
timeSheet.timesheetRows.add(timeSheetRow)
}
yourClass.timeSheetList.add(timeSheet)
}
}
}
Its "bindTo" method is the key piece of logic that understands how to get parameters from the incomming request and map it to a regular object. That object is of type "YourClass" and it looks like this:
class YourClass {
String loginName
Collection<TimeSheet> timeSheetList = []
String overallStatus
}
all other classes that are part of that class:
class TimeSheet {
String periodBegin
String periodEnd
Collection<TimeSheetRow> timesheetRows = []
}
and the last one:
class TimeSheetRow {
String task
String description
String paycode
}
Hope this example is clear enough for you and answers your question
Edit: Extending the answer according to the new requirements
Looking at your new code, I see that you probably did some typos when writting that post
def jsonArray = jsonArray.timesheetList
should be:
def jsonArray = jsonObject.timesheetList
but you obviously have it properly in your code since otherwise it would not work, then the same with that line with "println":
jsonArray1.size()
shuold be:
jsonArray.size()
and the essential fix:
def object1 = jsonArray[1]
shuold be
def object1 = jsonArray[0]
your array is of size==1, the indexing starts with 0. // Can it be that easy? ;)
Then "object1" is again a JSONObject, so you can access the fields with a "." or as a map, for example like this:
object1.get('periodEnd')
I see your example contains errors, which lead you to implement more complex JSON parsing solutions.
I rewrite your sample to the working version. (At least now for Grails 3.x)
String saveJSON // This holds the above JSON string.
def jsonObject = grails.converters.JSON.parse(saveJSON)
println jsonObject.timesheetList // output timesheetList structure
println jsonObject.timesheetList[0].timesheetRows[1] // output second element of timesheetRows array: [paycode:payCode2, task:painting, activityDescription:painting description]