Post data containing array of structs in swift - json

Here is the JSON I need to post:
{
"results": [
{
"case_id": 1,
"status_id": 5,
"comment": "This test failed"
},
{
"case_id": 2,
"status_id": 1,
"comment": "This test passed",
},
..
{
"case_id": 1,
"assignedto_id": 5,
"comment": "Assigned this test to Joe"
}
..
]
}
What I've tried doing is this :
let parameters = [
"results" : data
] as [String : Any]
let postData = try JSONSerialization.data(withJSONObject: parameters, options: [])
Here, data is an array of structs of the type (data:[param]) :
struct param {
var status_id: Int
var case_id: String
var comment: String
}
The code fails at JSONSerialization. It enters the catch() block. I tried giving the parameters like this and it worked,
let parameters = [ "results" : [
[
"case_id": "20275",
"status_id": 5,
"comment": "This test failed"
],
[
"case_id": "20276",
"status_id": 1,
"comment": "This test passed",
],
]] as [String : Any]
How can I reproduce this structure? Because I can't hard code the values of status id's and case id's. I store the status id's and case id's in arrays.I thought creating an array of structs and substituting the id values will be enough, unfortunately it's not working. How do I post the data then?

The 'param' should be a dictionary do not make it with struct.
The request body data type is: [String:[[String,Any]]]

Related

Swift : How to create a dictionary dynamically from a json?

I'd like some advice from you. I would like to create a dictionary from a dynamic response fetch from an API and send that dictionary in an Alamofire POST request.
From what I have so far it's working but I'm not satisfied with what i've made and I think the code is really messy.
Here is an example of what I can receive
"content": {
"type": "form",
"fields": [
{
"type": "select",
"label": "Do you have your documents?",
"field": "user.has_docs",
"default": 0,
"choices": [
{
"value": 0,
"name": "Not yet"
},
{
"value": 1,
"name": "I do"
}
]
},
{
"type": "input",
"field": "user.date",
"label": "When do you arrive?",
}
]
}
After parsing the json with the Codable protocol, I have all my data in the Model Field
type: String
label: String
field: String
defaultValue: Int?
choice: [Choice]?
Choice
value: Int
name: String
So I want to create my dictionary and I want the following scheme :
{
"value": {
"user": {
"has_docs": 1,
"date": "29/07/2020"
}
}
}
The key named : "value" is always the same value, but the other one depends of the result from the API. the prefix of the field corresponding of "parent object" and the right part is the child.
Hard coding a dictionary in Swift is not that hard, I would do
let dict = [
"value": [
"user": [
"has_docs": 1,
"date": "29/07/2020"
]
]
]
But the troubles begin, at the attempt of creating a dictionary dynamically. Values inside user keep only the last one and replacing has_docs with date.
I have found a workaround with using flatmap and reduce but it only allows the type [String: String], unfortunately I need to write [String: Int] too in the dictionary.
here is a sample of the code
let flattenedDictionary = [key : dictionaries
.flatMap { $0 }
.reduce([String:String]()) { (dict, tuple) in
var nextDict = dict
nextDict.updateValue(tuple.1 as! String, forKey: tuple.0)
return nextDict
}]
parameters["value"] = flattenedDictionary
Here :
key = "user".
dictionaries = [["has_docs": 1], ["date": "29/07/2020"]]
Feel free to exchange if you need more informations
If you have any clue on how you could helping me, I'll highly appreciate, thanks for reading so far.
I hope I was very understandable.
Edit
From a general view : I'd like to create a dictionary dynamically
[String: [String: [String: Any]]]
A bit unclear if you have a [String: [String: [String: Any]]] or [String: [String: Any]] dictionary, but the concept of creating it dynamically would be rather similar.
var user: [String: Any] = [:]
user["has_docs"] = 1
user["date"] = Date()
let dict = ["value": user]

Casting dictionary of sets to JSON Object

I'm trying to build request body like this form:
{
"user": {
"id": 1,
"id": 2,
"id": 4
}
}
My first idea was built json from string and cast it to dictionary String and Any, but this solution have a issue. Some "id" are missing on casting by JSONSerialization step.
I tried to use:
var dictionary: [String : Any] = ["name" : "John"]()
var selectedIDs = Set<NSDictionary>()
// Adding values to selectedIDs set
let userIDDict = ["id" : id] as NSDictionary
selectedIDs.insert(userIDDict)
dictionary.updateValue(selectedIDs, forKey: "user")
But it cannot be cast by JSONSerialization (Invalid type in JSON write).
How can i resolve problem, which i'm facing?
Creating this request is not a problem; it's just not proper JSON, so you shouldn't try to use JSONSerialization. It's just a string, and so you can create that string:
let idKeyValues = ids.map { "\"id\": \($0)" }.joined(separator: ",\n ")
let request = """
{
"user": {
\(idKeyValues)
}
}
"""
===>
{
"user": {
"id": 1,
"id": 2,
"id": 4
}
}
The proper way to express this in JSON would be:
{
"user": {
"ids": [1, 2, 4]
}
}
With that, a Codable implementation should be very straightforward.

One of the elements of the array as an object

The question is how to get the "from" element? The rest is not a problem
I know that in https://github.com/json-iterator/ it can be done, but I could not figure out how it works there
Json:
{
"ab": 123456789,
"cd": [
[
4,
1234,
123456,
1000000001,
1234567890,
"text",
{
"from": "123456"
}
],
[
4,
4321,
654321,
1000000001,
9876543210,
"text",
{
"from": "654321"
}
]
]
}
Golang:
type test struct {
Ab int `json:"ab"`
Cd [][]interface{} `json:"cd"`
}
var testvar test
json.Unmarshal(Data, &testvar)
testvar.Cd[0][6]["from"].(string)
Error:
invalid operation: testvar.Cd[0][6]["from"] (type interface {} does not support indexing)
It's simple: it is a map[string]interface{} hence
m, ok := testvar.Cd[0][6].(map[string]interface{})
fmt.Println(m, ok, m["from"])
https://play.golang.org/p/XJGs_HsxMfZ

Ruby: How to parse json to specific types

I have a JSON that I want to parse in Ruby. Ruby is completely new to me, but I have to work with it :-)
Here is my litte snippet, that should do the parsing:
response = File.read("app/helpers/example_announcement.json")
JSON.parse(response)
this works pretty fine. The only downside is, I do not know the properties at the point where I use it, it is not typesafe. So I created the objects for it
class Announcements
##announcements = Hash # a map key => value where key is string and value is type of Announcement
end
class Announcement
##name = ""
##status = ""
##rewards = Array
end
And this is how the json looks like
{
"announcements": {
"id1" : {
"name": "The Diamond Announcement",
"status": "published",
"reward": [
{
"id": "hardCurrency",
"amount": 100
}
]
},
"id2": {
"name": "The Normal Announcement",
"players": [],
"status": "published",
"reward": []
}
}
}
So I tried JSON parsing like this
response = File.read("app/helpers/example_announcement.json")
JSON.parse(response, Announcements)
But this is not how it works^^can anybody help me with this?

Alamofire POST Request

I was hoping someone could explain what the POST request (with parameters) accomplishes. When I run the following command, provided by Alamofire's documentation, this is what is produced:
Code
let url = "https://httpbin.org/post"
let parameters: Parameters = [
"foo": "bar",
"baz": ["a", 1],
"qux": [
"x": 1,
"y": 2,
"z": 3
]
]
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in
if((response.result.value) != nil) {
let jsonVar: JSON = JSON(response.result.value!)
print(jsonVar)
}
}
Result
{
"files" : {
},
"origin" : "192.104.181.247",
"data" : "{\"baz\":[\"a\",1],\"qux\" {\"y\":2,\"x\":1,\"z\":3},\"foo\":\"bar\"}",
"headers" : {
"Accept" : "*\/*",
"Accept-Encoding" : "gzip;q=1.0, compress;q=0.5",
"Content-Type" : "application\/json",
"Host" : "httpbin.org",
"Content-Length" : "53",
"User-Agent" : "HTTPRequest\/1.0 (com.dexstrum.HTTPRequest; build:1; iOS 10.2.0) Alamofire\/4.3.0",
"Accept-Language" : "en;q=1.0"
},
"json" : {
"baz" : [
"a",
1
],
"foo" : "bar",
"qux" : {
"x" : 1,
"y" : 2,
"z" : 3
}
},
"form" : {
},
"args" : {
},
"url" : "https:\/\/httpbin.org\/post"
}
What exactly is occurring with the parameters and the POST request?
The url you are hitting it allows a post request. You can get json response by get or post method. Usually you fetch data by get method and send data by post method. When sending data with post request it needs some parameter to satisfy its requirement , usually its predefined.
SO you are sending a post request here with alamofire and along with some parameter which satisfy its requirements. Here you are encoding the parameter as JSONEncoding.default which means it sends the parameter data encoded as json finally you get the response as json coz you declared .responseJSON . Hope that helps.