How to iterate through array to pull out properties for specifc keys? - ios

Im working with decoded JSON, and specifically i need to work within an array to pull out a property of a specific object based on its key.
JSON looks like the following, and Im needing to pull out the filenames for "fanart" and "clearlogo"
{
"code": 200,
"status": "Success",
"data": {
"count": 1,
"base_url": {
"original": "https://cdn.thegamesdb.net/images/original/",
"small": "https://cdn.thegamesdb.net/images/small/",
"thumb": "https://cdn.thegamesdb.net/images/thumb/",
"cropped_center_thumb": "https://cdn.thegamesdb.net/images/cropped_center_thumb/",
"medium": "https://cdn.thegamesdb.net/images/medium/",
"large": "https://cdn.thegamesdb.net/images/large/"
},
"images": {
"2578": [
{
"id": 5512,
"type": "boxart",
"side": "front",
"filename": "boxart/front/2578-1.jpg",
"resolution": "1533x2155"
},
{
"id": 5513,
"type": "boxart",
"side": "back",
"filename": "boxart/back/2578-1.jpg",
"resolution": "1522x2155"
},
{
"id": 87092,
"type": "fanart",
"side": null,
"filename": "fanart/2578-1.jpg",
"resolution": "1920x1080"
},
{
"id": 87093,
"type": "fanart",
"side": null,
"filename": "fanart/2578-2.jpg",
"resolution": "1920x1080"
},
{
"id": 87094,
"type": "fanart",
"side": null,
"filename": "fanart/2578-3.jpg",
"resolution": "1920x1080"
},
{
"id": 87095,
"type": "clearlogo",
"side": null,
"filename": "clearlogo/2578.png",
"resolution": "400x300"
},
{
"id": 87096,
"type": "screenshot",
"side": null,
"filename": "screenshots/2578-1.jpg",
"resolution": null
},
{
"id": 87097,
"type": "screenshot",
"side": null,
"filename": "screenshots/2578-2.jpg",
"resolution": null
},
{
"id": 87098,
"type": "fanart",
"side": null,
"filename": "fanart/2578-4.jpg",
"resolution": "1920x1080"
},
{
"id": 87099,
"type": "screenshot",
"side": null,
"filename": "screenshots/2578-3.jpg",
"resolution": null
},
{
"id": 87100,
"type": "screenshot",
"side": null,
"filename": "screenshots/2578-4.jpg",
"resolution": null
},
{
"id": 87101,
"type": "fanart",
"side": null,
"filename": "fanart/2578-5.jpg",
"resolution": "1920x1080"
}
]
}
},
The key "2578"is dynamic and changes by the game. I have this succesfuly decoding with the following:
struct GameDBData : Decodable {
let data : GameDataImages
}
struct GameDataImages : Decodable {
let images : Images
}
struct Images : Decodable {
var innerArray: [String: [Inner]]
struct Inner: Decodable {
let id : Int
let fileName : String
let type : String
enum CodingKeys : String, CodingKey {
case id
case fileName = "filename"
case type
}
}
private struct CustomCodingKeys: CodingKey {
var stringValue : String
init?(stringValue : String) {
self.stringValue = stringValue
}
var intValue: Int?
init?(intValue: Int) {
return nil
}
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CustomCodingKeys.self)
self.innerArray = [String: [Inner]]()
for key in container.allKeys {
let value = try container.decode([Inner].self, forKey: CustomCodingKeys(stringValue: key.stringValue)!)
self.innerArray[key.stringValue] = value
}
}
}
Ive tried firstIndex(where:) but Im not getting anywhere with it. How can i iterate the 2578 array to get the filename for type: "clearlogo" and type: "fanart" im needing?

You have array of Inner.Something like this,
var array:[Inner] = [_yourData]
If we assume your array should have only one object with type "fanart" & "clearlogo" for each.we can get each filename using ,
let fanartFileName = array.filter({$0.type == "fanart"})[0].fileName
let clearlogoFileName = array.filter({$0.type == "clearlogo"})[0].fileName
some times your array havn't any record for these types.or have more than one,
let fanartArray = ar.filter({$0.type == "fanart"})
if fanartArray.count > 0 {
fanartArray.forEach { (record) in
print(record.fileName)
}
}

Related

How to bypass errors and parse json field values

How to deserialize below JSON?
When i am using below code
Response response=engine.getResponse(Method.GET,strURL,strBAUsername,strBAPassword,null,ContentType.JSON);
userEdit=response.as(TestUserRoleInfoList.class); // TestUserRoleInfoList is a POJO class
#JsonIgnoreProperties(ignoreUnknown=true)
public class TestUserRoleInfoList {
#JsonProperty("userRoleInfoList")
List<UserRoleInfo> userRoleInfo=new ArrayList<UserRoleInfo>();
public List<UserRoleInfo> getUserRoleInfo() {
return userRoleInfo;
}
public void setUserRoleInfo(List<UserRoleInfo> userRoleInfo) {
this.userRoleInfo = userRoleInfo;
}
}
Somehow it unable to parse Regions internal class. But i am least bothered. I need collectionRole fields.
How can i get the list of collection roles?
{
"id": 5595,
"userName": "abc",
"firstName": "abc",
"lastName": "ijk",
"additionalName": "Ernest",
"namePrefix": {
"id": null,
"prefix": null,
"createdAt": null,
"updatedAt": null
},
"nameSuffix": {
"id": null,
"suffix": null,
"createdAt": null,
"updatedAt": null
},
"emplId": "11111",
"workDayId": "11111",
"staffEmailAddress": null,
"facultyEmailAddress": "abc.xyz#xxxx.edu",
"userRoleInfoList": [
{
"userId": 5595,
"collectionRole": "program-chair",
"regions": [
{
"id": 1,
"region": "Germany 1",
"regionalDirectorFirstName": "aaaa",
"regionalDirectorLastName": "bbbb",
"associateDirectorFirstName": null,
"associateDirectorLastName": null,
"division": {
"id": 2,
"name": "Europe",
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
},
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
}
],
"school": {
"id": 3,
"name": "Arts and Sciences",
"dean": null,
"createdAt": null,
"updatedAt": null
},
"facultyPhoto": null,
"primary": false
},
{
"userId": 5595,
"collectionRole": "faculty",
"regions": [
{
"id": 3,
"region": "Germany 1",
"regionalDirectorFirstName": "aaaa",
"regionalDirectorLastName": "bbbb",
"associateDirectorFirstName": null,
"associateDirectorLastName": null,
"division": {
"id": 2,
"name": "Europe",
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
},
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
}
],
"school": {
"id": 3,
"name": "Arts and Sciences",
"dean": null,
"createdAt": null,
"updatedAt": null
},
"facultyPhoto": null,
"primary": true
}
]
}
You can use org.json.JSONObject
Response response = when()
.get("api_url")
.then()
.extract().response();
JSONObject jsonObject = new JSONObject(response.getBody().asString());
JSONArray jsonArray = jsonObject.getJSONArray("userRoleInfoList");
List<String> stringList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
stringList.add(jsonArray.getJSONObject(i).getString("collectionRole"));
}
System.out.println(stringList);
This will output [program-chair, faculty]

How to use a dictionary from JSON with Realm?

Creating a data model to use with codable and realm. Im getting stuck on dictionaries. As I understand it, you cannot use dictionaries with realm? How can I decode the following JSON and use it with something Realm will accept?
JSON Example A
"platform": {
"data": {
"25": {
"id": 25,
"name": "3DO",
"alias": "3do"
},
"4944": {
"id": 4944,
"name": "Acorn Archimedes",
"alias": "acorn-archimedes"
},
"4954": {
"id": 4954,
"name": "Acorn Electron",
"alias": "acorn-electron"
}
}
Note, the keys are strings that change, in decoable form i have it as
StructExample A
struct PlatformData : Codable {
let data : [String: PlatformInformation]
}
JSON Example B
"include": {
"boxart": {
"base_url": {
"original": "https:\/\/cdn.thegamesdb.net\/images\/original\/",
"small": "https:\/\/cdn.thegamesdb.net\/images\/small\/",
"thumb": "https:\/\/cdn.thegamesdb.net\/images\/thumb\/",
"cropped_center_thumb": "https:\/\/cdn.thegamesdb.net\/images\/cropped_center_thumb\/",
"medium": "https:\/\/cdn.thegamesdb.net\/images\/medium\/",
"large": "https:\/\/cdn.thegamesdb.net\/images\/large\/"
},
"data": {
"1":
[
{
"id": 242,
"type": "fanart",
"side": null,
"filename": "fanart\/1-2.jpg",
"resolution": "1920x1080"
},
{
"id": 433,
"type": "fanart",
"side": null,
"filename": "fanart\/1-5.jpg",
"resolution": "1920x1080"
}
],
"2":
[
{
"id": 15,
"type": "fanart",
"side": null,
"filename": "fanart\/2-1.jpg",
"resolution": "1920x1080"
},
{
"id": 133,
"type": "fanart",
"side": null,
"filename": "fanart\/2-2.jpg",
"resolution": "1920x1080"
},
{
"id": 656,
"type": "fanart",
"side": null,
"filename": "fanart\/2-4.jpg",
"resolution": "1920x1080"
}
],
"4":
[
{
"id": 208,
"type": "fanart",
"side": null,
"filename": "fanart\/4-1.jpg",
"resolution": "1920x1080"
},
{
"id": 481,
"type": "banner",
"side": null,
"filename": "graphical\/4-g.jpg",
"resolution": null
},
{
"id": 846,
"type": "boxart",
"side": "front",
"filename": "boxart\/front\/4-1.jpg",
"resolution": "1000x705"
},
{
"id": 847,
"type": "boxart",
"side": "back",
"filename": "boxart\/back\/4-1.jpg",
"resolution": "1000x705"
},
{
"id": 73897,
"type": "clearlogo",
"side": null,
"filename": "clearlogo\/4.png",
"resolution": "400x148"
},
{
"id": 215539,
"type": "fanart",
"side": null,
"filename": "fanart\/4-2.jpg",
"resolution": null
},
{
"id": 238533,
"type": "screenshot",
"side": null,
"filename": "screenshot\/4-1.jpg",
"resolution": null
},
{
"id": 238534,
"type": "screenshot",
"side": null,
"filename": "screenshot\/4-2.jpg",
"resolution": null
},
{
"id": 238535,
"type": "screenshot",
"side": null,
"filename": "screenshot\/4-3.jpg",
"resolution": null
},
{
"id": 238536,
"type": "screenshot",
"side": null,
"filename": "screenshot\/4-4.jpg",
"resolution": null
},
{
"id": 238537,
"type": "screenshot",
"side": null,
"filename": "screenshot\/4-5.jpg",
"resolution": null
},
{
"id": 238538,
"type": "screenshot",
"side": null,
"filename": "screenshot\/4-6.jpg",
"resolution": null
}
],
"5":
[
{
"id": 396,
"type": "banner",
"side": null,
"filename": "graphical\/5-g.jpg",
"resolution": null
},
{
"id": 2364,
"type": "fanart",
"side": null,
"filename": "fanart\/5-4.jpg",
"resolution": "1920x1080"
},
]
Here is similar, except now with an array of objects as the value
Struct Example B
struct BoxArtData : Codeable {
let data: [String:[ExtraImages]]
}

Nifi RecordReader & RecordWriter serialization error. IllegalTypeConversionException; Cannot convert value of class; because the type is not supported

I'm trying to convert json to json using JoltTransformRecord in Apache Nifi. When I try transform json in https://jolt-demo.appspot.com/, I'm getting correct result. This is okey.
But, when I'm trying to transform json using JoltTransformRecord, it is throws an exception. Error is; "Cannot convert value of class [Ljava.lang.Object; because the type is not supported". But I didn't understand why I'm getting this error. I did check my input and output schemas, but I didn't find anything. They looks like correct.
In the below, my input and output json examples, jolt specification, input and output schemas are given. Also, for this, I'm using JsonTreeReader and JsonRecordSetWriter.
--- How can I solve this problem? ---
Example input json for JoltTransformRecord(In this example, there is only one json object inside array. But actually, there are a lot of json object inside array.);
[ {
"uuid" : "MFMS1-MC5",
"componentId" : "path1",
"Samples" : {
"PathFeedrate" : [ {
"dataItemId" : "pf",
"timestamp" : "2019-03-01T21:48:27.940558Z",
"sequence" : "68104",
"value" : "425.5333",
"name" : "Fact",
"subType" : "ACTUAL"
}, {
"dataItemId" : "pf",
"timestamp" : "2019-03-01T21:48:30.244219Z",
"sequence" : "68117",
"value" : "0",
"name" : "Fact",
"subType" : "ACTUAL"
} ]
},
"Events" : {
"SequenceNumber" : [ {
"dataItemId" : "seq",
"timestamp" : "2019-03-01T21:48:27.940558Z",
"sequence" : "68105",
"value" : "0",
"name" : "sequenceNum"
} ],
"Unit" : [ {
"dataItemId" : "unit",
"timestamp" : "2019-03-01T21:48:27.940558Z",
"sequence" : "68106",
"value" : "13",
"name" : "unitNum"
} ]
}
}]
Sample output Json I want;
{
"DataItems" : [ {
"uuid" : "MFMS1-MC5",
"componentId" : "path1",
"eventType" : "Samples",
"type" : "PathFeedrate",
"dataItemId" : "pf",
"timestamp" : "2019-03-01T21:48:27.940558Z",
"sequence" : "68104",
"value" : "425.5333",
"name" : "Fact",
"subType" : "ACTUAL"
}, {
"uuid" : "MFMS1-MC5",
"componentId" : "path1",
"eventType" : "Samples",
"type" : "PathFeedrate",
"dataItemId" : "pf",
"timestamp" : "2019-03-01T21:48:30.244219Z",
"sequence" : "68117",
"value" : "0",
"name" : "Fact",
"subType" : "ACTUAL"
}, {
"uuid" : "MFMS1-MC5",
"componentId" : "path1",
"eventType" : "Events",
"type" : "SequenceNumber",
"dataItemId" : "seq",
"timestamp" : "2019-03-01T21:48:27.940558Z",
"sequence" : "68105",
"value" : "0",
"name" : "sequenceNum"
}, {
"uuid" : "MFMS1-MC5",
"componentId" : "path1",
"eventType" : "Events",
"type" : "Unit",
"dataItemId" : "unit",
"timestamp" : "2019-03-01T21:48:27.940558Z",
"sequence" : "68106",
"value" : "13",
"name" : "unitNum"
} ]
}
My Jolt Specification;
[
{
"operation": "shift",
"spec": {
"Samples": {
"*": {
"*": {
"#(3,uuid)": "Items.&2[#2].uuid",
"#(3,componentId)": "Items.&2[#2].componentId",
"$2": "Items.&2[#2].eventType",
"$1": "Items.&2[#2].type",
"*": "Items.&2[#2].&"
}
}
},
"Events": {
"*": {
"*": {
"#(3,uuid)": "Items.&2[#2].uuid",
"#(3,componentId)": "Items.&2[#2].componentId",
"$2": "Items.&2[#2].eventType",
"$1": "Items.&2[#2].type",
"*": "Items.&2[#2].&"
}
}
},
"Condition": {
"*": {
"*": {
"#(3,uuid)": "Items.&2[#2].uuid",
"#(3,componentId)": "Items.&2[#2].componentId",
"$2": "Items.&2[#2].eventType",
"$1": "Items.&2[#2].value",
"*": "Items.&2[#2].&"
}
}
}
}
},
{
"operation": "shift",
"spec": {
"Items": {
"*": {
"*": "DataItems[]"
}
}
}
}
]
This specification is working correctly. Because I have tried it in Jolt transform demo.
I'm using JsonTreeReader for read json in JoltTransformRecord. And this is my input schema;
{
"name": "Items",
"namespace": "Items",
"type": "record",
"fields": [
{
"name": "uuid",
"type": "string"
},
{
"name": "componentId",
"type": "string"
},
{
"name": "Samples",
"type": ["null", {
"type": "map",
"values": {
"type": "array",
"items": {
"name": "SamplesDataItem",
"type": "record",
"fields": [
{
"name": "dataItemId",
"type": "string"
},
{
"name": "timestamp",
"type": "string"
},
{
"name": "sequence",
"type": "string"
},
{
"name": "value",
"type": "string"
},
{
"name": "name",
"type": ["null", "string"]
},
{
"name": "subType",
"type": ["null", "string"]
},
{
"name": "sampleRate",
"type": ["null", "string"]
},
{
"name": "statistic",
"type": ["null", "string"]
},
{
"name": "duration",
"type": ["null", "string"]
},
{
"name": "sampleCount",
"type": ["null", "string"]
},
{
"name": "compositionId",
"type": ["null", "string"]
},
{
"name": "resetTriggered",
"type": ["null", "string"]
}
]
}
}
}]
},
{
"name": "Events",
"type": ["null", {
"type": "map",
"values": {
"type": "array",
"items": {
"name": "EventsDataItem",
"type": "record",
"fields": [
{
"name": "dataItemId",
"type": "string"
},
{
"name": "timestamp",
"type": "string"
},
{
"name": "sequence",
"type": "string"
},
{
"name": "value",
"type": "string"
},
{
"name": "name",
"type": ["null", "string"]
},
{
"name": "subType",
"type": ["null", "string"]
},
{
"name": "compositionId",
"type": ["null", "string"]
},
{
"name": "resetTriggered",
"type": ["null", "string"]
}
]
}
}
}]
},
{
"name": "Condition",
"type": ["null", {
"type": "map",
"values": {
"type": "array",
"items": {
"name": "ConditionDataItem",
"type": "record",
"fields": [
{
"name": "dataItemId",
"type": "string"
},
{
"name": "timestamp",
"type": "string"
},
{
"name": "type",
"type": "string"
},
{
"name": "sequence",
"type": "string"
},
{
"name": "name",
"type": ["null", "string"]
},
{
"name": "subType",
"type": ["null", "string"]
},
{
"name": "nativeCode",
"type": ["null", "string"]
},
{
"name": "nativeSeverity",
"type": ["null", "string"]
},
{
"name": "qualifier",
"type": ["null", "string"]
},
{
"name": "statistic",
"type": ["null", "string"]
},
{
"name": "compositionId",
"type": ["null", "string"]
}
]
}
}
}]
}
]
}
I'm using JsonRecordSetWriter for write converted result in JoltTransformRecord. And this is my output schema;
{
"name": "Items",
"type": "record",
"namespace": "Items",
"fields": [
{
"name": "DataItems",
"type": {
"type": "array",
"items": {
"name": "DataItems",
"type": "record",
"fields": [
{
"name": "uuid",
"type": "string"
},
{
"name": "componentId",
"type": "string"
},
{
"name": "eventType",
"type": "string"
},
{
"name": "type",
"type": "string"
},
{
"name": "dataItemId",
"type": "string"
},
{
"name": "timestamp",
"type": "string"
},
{
"name": "value",
"type": "string"
},
{
"name": "name",
"type": ["null", "string"],
"default": null
},
{
"name": "subType",
"type": ["null", "string"],
"default": null
}
]
}
}
}
]
}
This is indeed a bug in the record handling utilities, I have written NIFI-6105 to cover the fix. Good catch!
As a workaround, since you have JSON as input and output, you can use JoltTransformJson instead of JoltTransformRecord. Alternatively, if you know the keys in the map (PathFeedrate, e.g.), you can change the schema to treat it as a record rather than a map, that might get you around the bug.

Swagger array of different objects

For example I need to represent following structure in swagger yaml format:
"included": [
{
"type": "people",
"id": "42",
"attributes": {
"name": "John",
"age": 80,
"gender": "male"
}
}
]
With single object everything is fine:
included:
type: "array"
items:
type: object
properties:
type:
type: "string"
# and so on
The question is what if I need to describe something like:
"included": [{
"type": "people",
"id": "9",
"attributes": {
"first-name": "Dan",
"last-name": "Gebhardt",
"twitter": "dgeb"
},
"links": {
"self": "http://example.com/people/9"
}
}, {
"type": "comments",
"id": "5",
"attributes": {
"body": "First!"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "2" }
}
},
"links": {
"self": "http://example.com/comments/5"
}
}, {
"type": "comments",
"id": "12",
"attributes": {
"body": "I like XML better"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "9" }
}
},
"links": {
"self": "http://example.com/comments/12"
}
}]
I know that in OpenAPI it's possible ( aka swagger 3 ) and tried some workarounds in current version but with no luck.

How to send JSON response to another view in Swift 3

I have a problem with sending a JSON response from UITableView into another UITableView.
I want to send the Products array like in the code below into another UITableViewController based on the selected row on the TableView, but when I log the value in didSelectRowAt it returns nil.
So here's the JSON return.
{
"error_description": [],
"results": [
{
"id": 2,
"name": "Ernser, Kilback and Kreiger LLC",
"address": "48788 Adaline Ville 7634 Bertram Shoal",
"contact_person": "Coralie Schaden",
"mobile_number": "(238) 076-0562",
"image": {
"url": null,
"thumb": {
"url": null
},
"medium": {
"url": null
},
"small": {
"url": null
},
"icon": {
"url": null
}
},
"registered_at": "2017-01-10T04:16:52.621Z",
"products": [
{
"id": 21,
"name": "Fantastic Rubber Car",
"image": {
"url": null,
"thumb": {
"url": null
},
"medium": {
"url": null
},
"small": {
"url": null
},
"icon": {
"url": null
}
},
"points": 0,
"merchant_id": 2,
"created_at": "2017-01-10T04:16:52.630Z",
"updated_at": "2017-01-10T04:16:52.636Z"
},
{
"id": 22,
"name": "Mediocre Plastic Shirt",
"image": {
"url": null,
"thumb": {
"url": null
},
"medium": {
"url": null
},
"small": {
"url": null
},
"icon": {
"url": null
}
},
"points": 15,
"merchant_id": 2,
"created_at": "2017-01-10T04:16:52.819Z",
"updated_at": "2017-01-10T04:16:52.827Z"
},
]
}
This is a part of my code for getting the response.
I used the Alamofire
var merchantModel: Merchant!
var merchantArr = [Merchant]()
var productArr = [Product]()
var productModel : Product?
.....
case .success:
let json = JSON(data: response.data!)
for result in json["results"].arrayValue{
guard let merchantID = result["id"].number, let merchantName = result["name"].string, let merchantAddress = result["address"].string, let contactPerson = result["contact_person"].string, let mobilenumber = result["mobile_number"].string else{
return
}
self.merchantModel = Merchant(merchantID: merchantID, merchantName: merchantName, merchantAddress: merchantAddress, contactPerson: contactPerson, mobileNumber: mobilenumber, merchantImage: contactPerson)
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(self.merchantModel!, toFile: Merchant.ArchiveURL.path)
if !isSuccessfulSave {
print("Failed to save sender...")
}
for prodArr in result["products"].arrayValue{
print("prodArr:\(prodArr)")
guard let prodID = prodArr["id"].number, let prodName = prodArr["name"].string,
let points = prodArr["points"].number else{
return
}
self.productModel = Product(productID: prodID, productName: prodName, productPoints: points)
}
self.merchantArr.append(self.merchantModel!)
self.productArr.append(self.productModel!)
self.merchantModel.loadMerchant()
self.tableView.reloadData()
}
Swift is not javascript, and JSON is not the simplest way to handle the data in this language.
You'd probably prefer to transform your JSON data into Foundation objects, manipulate them, create UITableView with them... And when you'll need to have the JSON format again, you transform those Foundation objects back to JSON.
There are a lot of ways to achieve that, and some amazing third-party libraries to do it very easily. However for a start I encourage you to have a look at Apple's resources :
NSJSONSerialization
Working with JSON in Swift

Resources