Skip to content

Retrieving JSON Data

JSON values are stored in database columns of type JSON. The data retrieval mechanism for JSON values is the same as for any other data stored in Backendless database. You can use the data retrieval API to retrieve objects from the Backendless database. Data in the JSON columns is returned to the client application as either a strongly-typed object or as . Consider the example below:

Suppose the database stores objects in the Person data table. The table declares the profile column of type JSON. The column contains JSON values in the following format:

{
  "age": 55,
  "name": "Bob",
  "address": {
    "city": "Los Angeles",
    "state": "California",
    "street": "123 Santa Monica Blvd."
  },
  "lastname": "Smith",
  "favoriteColors": [
    "Blue", "Red"
  ],
  "favoriteNumbers": [
    13, 21, 88
  ]
}

As you can see the sample JSON value above exhibits the following "qualities":

  • literal string and numeric values - age, name and lastname keys.
  • an array consisting of strings - favoriteColors
  • an array consisting of numbers - favoriteNumbers
  • an enclosed JSON object in the address key.

The JSON values and the Person objects may appear as shown below in the database:

sample-json-database

Suppose the client application needs to retrieve both Person objects and the corresponding profile values as dictionary objects. This can be accomplished with the following code:

[[Backendless.shared.data ofTable:@"Person"] findByIdWithObjectId:@"1316FEE4-92A6-4400-9D08-EB243BF57671" responseHandler:^(NSDictionary *person) {

    NSDictionary *profile = person[@"profile"];
    NSLog(@"Name %@", profile[@"name"]);
    NSLog(@"Last name %@", profile[@"lastname"]);
    NSLog(@"Age %@", profile[@"age"]);
    NSLog(@"Favorite numbers %@", profile[@"favoriteNumbers"]);
    NSLog(@"Favorite colors %@", profile[@"favoriteColors"]);

    NSDictionary *address = profile[@"address"];
    NSLog(@"Street %@", address[@"street"]);
    NSLog(@"City %@", address[@"city"]);
    NSLog(@"State %@", address[@"state"]);

} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
Backendless.shared.data.ofTable("Person").findById(objectId: "1316FEE4-92A6-4400-9D08-EB243BF57671", responseHandler: { person in

    guard let profile = person["profile"] as? [String : Any] else { return }
    print("Name \(profile["name"] as? String ?? "")")
    print("Last name \(profile["lastname"] as? String ?? "")")
    print("Age \(profile["age"] as? NSNumber ?? 0)")
    print("Favorite numbers \(profile["favoriteNumbers"] as? [NSNumber] ?? [NSNumber]())")
    print("Favorite colors \(profile["favoriteColors"] as? [String] ?? [String]())")

    guard let address = profile["address"] as? [String : Any] else { return }
    print("Street \(address["street"] as? String ?? "")")
    print("City \(address["city"] as? String ?? "")")
    print("State \(address["state"] as? String ?? "")")

}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

The code produces the following log output:

Name Bob
Last name Smith
Age 55
Favorite numbers [13, 21, 88]
Favorite colors [Blue, Red]
Street 123 Santa Monica Blvd.
City Los Angeles
State California

As you can see, the entire JSON structure is converted to a dictionary with all the key/value pairs becoming corresponding entries in the returned object.

Your application may use an alternative approach - representing objects in the Backendless database with strongly-typed classes. In the context of the example above, this means you will have the Person class defined in your application. But then there is a question of what data type to use for the profile property? In this case, you have a choice for how to represent the JSON values. You can use either strongly-typed objects or the dictionaryapproach described above. See the example below:

Person class:
@interface Person : NSObject

@property (strong, nonatomic) Profile *profile;

@end
Profile class:
@interface Profile : NSObject

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *lastname;
@property (strong, nonatomic) NSNumber *age;
@property (strong, nonatomic) Address *address;
@property (strong, nonatomic) NSArray<NSNumber *> *favoriteNumbers;
@property (strong, nonatomic) NSArray<NSString *> *favoriteColors;

@end
Address class:
@interface Address : NSObject

@property (strong, nonatomic) NSString *street;
@property (strong, nonatomic) NSString *city;
@property (strong, nonatomic) NSString *state;

@end
API to retrieve data from the database:
[[Backendless.shared.data of:[Person class]] findByIdWithObjectId:@"742A4482-D50A-43F0-AB7F-94C3DFEBD1F3" responseHandler:^(Person *person) {

    Profile *profile = person.profile;
    NSLog(@"Name %@", profile.name);
    NSLog(@"Last name %@", profile.lastname);
    NSLog(@"Age %@", profile.age);
    NSLog(@"Favorite numbers %@", profile.favoriteNumbers);
    NSLog(@"Favorite colors %@", profile.favoriteColors);

    Address *address = profile.address;
    NSLog(@"Street %@", address.street);
    NSLog(@"City %@", address.city);
    NSLog(@"State %@", address.state);

} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
Person class:
@objcMembers class Person: NSObject {
    var profile: Profile?
}
Profile class:
@objcMembers class Profile: NSObject {
   var name: String?
   var lastname: String?
   var age: NSNumber?
   var address: Address?
   var favoriteNumbers: [NSNumber]?
   var favoriteColors: [String]?
}
Address class:
@objcMembers class Address: NSObject {
   var street: String?
   var city: String?
   var state: String?
}
API to retrieve data from the database:
Backendless.shared.data.of(Person.self).findById(objectId: "1316FEE4-92A6-4400-9D08-EB243BF57671", responseHandler: { person in

    guard let person = person as? Person else { return }
    guard let profile = person.profile else { return }
    print("Name \(profile.name ?? "")")
    print("Last name \(profile.lastname ?? "")")
    print("Age \(profile.age ?? 0)")
    print("Favorite numbers \(profile.favoriteNumbers ?? [NSNumber]())")
    print("Favorite colors \(profile.favoriteColors ?? [String]())")

    guard let address = profile.address else { return }
    print("Street \(address.street ?? "")")
    print("City \(address.city ?? "")")
    print("State \(address.state ?? "")")

}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Person class:
@interface Person : NSObject

@property (strong, nonatomic) NSDictionary *profile;

@end
API to retrieve database object using the Person class:
[[Backendless.shared.data of:[Person class]] findByIdWithObjectId:@"1316FEE4-92A6-4400-9D08-EB243BF57671" responseHandler:^(Person *person) {

    NSDictionary *profile = person.profile;
    NSLog(@"Name %@", profile[@"name"]);
    NSLog(@"Last name %@", profile[@"lastname"]);
    NSLog(@"Age %@", profile[@"age"]);
    NSLog(@"Favorite numbers %@", profile[@"favoriteNumbers"]);
    NSLog(@"Favorite colors %@", profile[@"favoriteColors"]);

    NSDictionary *address = profile[@"address"];
    NSLog(@"Street %@", address[@"street"]);
    NSLog(@"City %@", address[@"city"]);
    NSLog(@"State %@", address[@"state"]);

} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
Person class:
@objcMembers class Person: NSObject {
    var profile: [String : Any]?
}
API to retrieve database object using the Person class:
Backendless.shared.data.of(Person.self).findById(objectId: "1316FEE4-92A6-4400-9D08-EB243BF57671", responseHandler: { person in

    guard let person = person as? Person else { return }
    guard let profile = person.profile else { return }
    print("Name \(profile["name"] as? String ?? "")")
    print("Last name \(profile["lastname"] as? String ?? "")")
    print("Age \(profile["age"] as? NSNumber ?? 0)")
    print("Favorite numbers \(profile["favoriteNumbers"] as? [NSNumber] ?? [NSNumber]())")
    print("Favorite colors \(profile["favoriteColors"] as? [String] ?? [String]())")

    guard let address = profile["address"] as? [String : Any] else { return }
    print("Street \(address["street"] as? String ?? "")")
    print("City \(address["city"] as? String ?? "")")
    print("State \(address["state"] as? String ?? "")")

}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

In case when the JSON values are represented as strongly-typed classes, Backendless automatically adapts them to the instances of your classes. It is important to maintain the basic fidelity between the JSON types and the corresponding  types as shown below:

JSON Type
Objective-C Type
Swift Type
string
NSString
String
number
NSNumber
NSNumber
boolean
NSNumber (represented as 0 or 1)or bool
Bool
object
custom class or NSDictionary
custom class orDictionary
array
NSArray
NSArray<NSNumber*>
NSArray<NSString*>
[Any]
[NSNumber]
[String]
[Bool]