Query local JSON File in Swift [duplicate] - json

This question already has answers here:
Search through a large json file for a particular key value pair
(2 answers)
Closed 5 years ago.
I have a local JSON file that I am trying to parse based on a value. I can correctly get all the values from the file but what's the best solution to get a particular value. let say i have the following JSON data
[{ "city" : "AGAWAM", "loc" : [ -72.622739, 42.070206 ], "pop" : 15338,
"state" : "MA", "_id" : "01001" }
, { "city" : "CUSHMAN", "loc" : [ -72.51564999999999, 42.377017 ],
"pop"
: 36963, "state" : "MA", "_id" : "01002" }
, { "city" : "BARRE", "loc" : [ -72.10835400000001, 42.409698 ], "pop"
: 4546, "state" : "MA", "_id" : "01005" }]
Say I only want to show line with _id = 01002. What would be the best solution to achieve what I am asking? I added what I already have, any help would be greatly appreciated.
if let file = Bundle.main.url(forResource: "zip", withExtension: "json") {
do {
let data = try Data(contentsOf: file)
let json = JSON(data: data)
let jsonRecord = json["_id"]
print("this is json \(jsonRecord)")
} catch {
// handle error
}
}

found my answer using different terminology
here
Swift array version:
let peopleNamedTom = arrayOfPeople.filter { $0["Name"] == "Tom" }
SwiftyJSON array version:
let peopleNamedTom = arrayOfPeople.filter { $1["Name"] == "Tom" }

Related

How to retrieve all key-value pairs avoiding key duplication from JSON in Groovy script

I am totally new to groovy script and would like some help to solve this out. I have a JSON response I want to manipulate and get desired parameters back by avoiding duplication. The Json response does not have indexes like 0,1,2.. that I can iterate through.
Here is the response that I want to work with:
{
"AuthenticateV2" : {
"displayName" : "Verification of authentication",
"description" : "notification ",
"smsTemplate" : "authentication.v2.0_sms",
"emailHeaderTemplate" : "v2.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE"
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordRecovery" : {
"displayName" : "Verification of password recovery",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "recovery.v1.0_body_html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordReset" : {
"displayName" : "password reset",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
}
The expected output that I want to have:
{
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL"
}
I need to retrieve all fields under parameters tag and also want to avoid duplication
You should first get familiar with parsing and producing JSON in Groovy.
Then, assuming the provided response is a valid JSON (it's not - there are 2 closing curlies (}) missing at the end) to get all the parameters keys merged into one JSON we have to convert the JSON string into a Map object first using JsonSlurper:
def validJsonResponse = '<your valid JSON string>'
Map parsedResponse = new JsonSlurper().parseText(validJsonResponse) as Map
Now, when we have a parsedResponse map we can iterate over all the root items in the response and transform them into the desired form (which is all the unique parameters keys) using Map::collectEntries method:
Map uniqueParameters = parsedResponse.collectEntries { it.value['parameters'] }
Finally, we can convert the uniqueParameters result back into a pretty printed JSON string using JsonOuput:
println JsonOutput.prettyPrint(JsonOutput.toJson(uniqueParameters))
After applying all the above we'll get the output
{
"displayName": "USER_DISPLAY_NAME",
"actionTokenURL": "VERIFICATION_LINK",
"customToken": "VERIFICATION_CODE",
"adminInitiated": false,
"authnId": "AUTHENTICATION_IDENTIFIER",
"authnType": "EMAIL",
"user": {
"displayName": "USER_DISPLAY_NAME"
}
}
If you want to get rid of user entry from the final output just remove it from the resulting uniqueParameters map (uniqueParameters.remove('user')) before converting it back to JSON string.

How to parse JSON object without JSONdecoder in iOS? [duplicate]

This question already has an answer here:
Decode Dictionary with Random Initial Key
(1 answer)
Closed 1 year ago.
Okay, so I received this werid JSON format couple days back, I don't know if it is possible to decode it but I would like to learn if we could.
{
"status" : true,
"orderHistory": {
"5" : {
"productId" : 0,
"productName" : "Anchovy",
"quantity" : 1,
"price" : "199"
"variation": ""
},
"17" : {
"productId" : 0,
"productName" : "Anchovy",
"quantity" : 1,
"price" : "199"
"variation": ""
},
"98" : {
"productId" : 0,
"productName" : "Anchovy",
"quantity" : 1,
"price" : "199"
"variation": ""
}
}
}
Order History is supposed to be an Array, but in this case backend is sending these Objects with random string keys, Reason we can't create a Decodable Model is that the keys are random,
Any ideas on how to decode this data and use it into our iOS app?
It is best to continue using the JSON decoder.
The root model matching the JSON would look like this:
struct Body: Decodable {
let status: Bool
let orderHistory: [String: Order]
}
The Order Model will be simple.

Sending Data to server in JSON format Swift

Server expecting from me data in JSON format . Like this ;
. Im trying to send data like this ;
func getProductListResponse(typeId : String , type : String) {
let tsoftFilter = [
"key" : type,
"value" : typeId
] as [String : AnyObject]
print("tsoft filter is \(tsoftFilter)")
let serviceParams = [
"store_id" : Config.productListId,
"page" : currentPage,
"per_page" : perPage,
"tsoft_filters" : "\(tsoftFilter)"
] as [String : AnyObject]
But it doesn't work where do I making mistake ?
You are adding the description of a dictionary which is not equal to JSON. And according to the screenshot you need even an array of dictionaries.
In this case it's easier to create the JSON literally
func getProductListResponse(typeId : String , type : String) {
let tsoftFilter = #"[{"key":"\(type)","value":"\(typeId)"}]"#
let serviceParams : [String : Any] = [
"store_id" : Config.productListId,
"page" : currentPage,
"per_page" : perPage,
"tsoft_filters" : tsoftFilter
]
...
By the way a parameter dictionary sent in a network request is never [String:AnyObject]
Try this:
let tsoftFilter = """
[
[ "key" : type, "value" : typeId]
]
"""

My JSON parsing fails

Im using SwiftyJSON, Alamofire_SwiftyJSON and Alamofire libraries. I'm trying to parse my response but it returns nothing("definitions" fails to print).
JSON isn't empty it has got the response.
So, my code looks like the following (nothing fails, it all compiles)
Alamofire.request(request).responseSwiftyJSON { dataResponse in
if let JSON = dataResponse.result.value {
print(JSON)
if let definitions = JSON["results"]["lexicalEntries"]["entries"]["senses"]["definitions"].string {
print(definitions)
print("Hello")
}}
}
My response model looks like (this is not the whole response, that's just what I want to reach :
{
"results" : [
{
"language" : "en",
"id" : "ace",
"type" : "headword",
"lexicalEntries" : [
{
"language" : "en",
"entries" : [
{
"etymologies" : [
"Middle English (denoting the ‘one’ on dice): via Old French from Latin as ‘unity, a unit’"
],
"grammaticalFeatures" : [
{
"type" : "Number",
"text" : "Singular"
}
],
"homographNumber" : "000",
"senses" : [
{
"definitions" : [
"a playing card with a single spot on it, ranked as the highest card in its suit in most card games"
I think that my problem is in, should I add any parentheses or any symbols?
if let definitions = JSON["results"]["lexicalEntries"]["entries"]["senses"]["definitions"].string
You are not indexing the corresponding arrays in your JSON response, to access the definitions array you can simply use
JSON['results'][0]['lexicalEntries'][0]['entries'][0]['senses'][0]['definitions']

appending optional elements to an array from json in Swift

I have just started getting familiar with JSON. I have a class object that I am initialising by passing in a JSON. This object has an array that may be empty and I need to check it for value. so far I am trying:
init(json: JSON) {
id = json["id"].string
type = json["type"].string
text = json["text"].string
answer = json["answer"].string
format = json["format"].string
answeredBy = []
if let answeredByjson = json["answeredBy"].array {
for (_, userDict) in answeredByjson {
if let userDict = userDict as? [String : Any] {
answeredBy.append(JSON(User(dictionary: userDict)))
}
}
}
}
the elements in the array are dictionaries that have to be used to initialize another object (User).
the error I am getting is:
Expression type '[JSON]' is ambiguous without more context.
How can I update my code?
this is my json:
{
"answer" : "rachel",
"answeredBy" : {
"j1K4WXbOFRXfm3srk9oMtZJ8Iop2" : {
"email" : "an email",
"pictureURL" : "a URL",
"uid" : "j1K4WXbOFRXfm3srk9oMtZJ8Iop2",
"name" : "a name"
},
"vtYlmyerugedizHyOW6TV847Be23" : {
"email" : "an email",
"pictureURL" : "a URL",
"uid" : "vtYlmyerugedizHyOW6TV847Be23",
"name" : "Rusty Shakleford"
}
},
"format" : "field",
"id" : "1",
"type" : "text",
"text" : "In a foot race, Jerry was neither first nor last. Janet beat Jerry, Jerry beat Pat. Charlie was neither first nor last. Charlie beat Rachel. Pat beat Charlie. Who came in last?"
}
if let answeredByjson = json["answeredBy"].array {
...
}
produces an array [JSON], but you expect it to produce a dictionary [String: JSON]. That is why you receive:
Expression type '[JSON]' is ambiguous without more context
To produce a dictionary:
if let answeredByjson = json["answeredBy"].dictionary {
...
}
It you don't expect it to produce a dictionary [String: JSON] then this line doesn't make sense
for (_, userDict) in answeredByjson {