Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm stuck on decoding a JSON in swift.
I've got the following code in a playground with a JSON that has 10 fields. When i try to decode the data I get the following Error
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
But this error does not seem to happen if I take out e.g. "ninth" and "tenth" or 2 of any of the other fields so only 8 fields remain in the struct.
Is there a limitation of only be able to have 8 fields decoded? Am I missing something?
is there anything i can do to overcome this issue?
My code snippet:
let decoder = JSONDecoder()
struct Positions: Codable {
let first : String
let second: String
let third: String
let forth: String
let fith: String
let sixth: String
let seventh: String
let eigth: String
let nineth: String
let tenth: String
}
var positions = """
{
"first" : "first",
"second": "second",
"third": "third",
"forth": "forth",
"fith": "fith",
"sixth": "sixth",
"seventh": "seventh",
"eigth": "eigth",
"nineth": "nineth",
"tenth": "tenth"
}
""".data(using: .utf8)
let result = try decoder.decode(Positions.self, from: positions!)
print("tr \(result)")
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 17 days ago.
The community reviewed whether to reopen this question 17 days ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have a JSON response in the following format:
{
"coordinates": [
"-0.88676",
"51.47533"
],
[
"-0.88646",
"51.47549"
]
}
I am struggling to parse this data and append each coordinates value into an array.
I can see that this is a dictionary array but if I try to parse as a dictionary I get an error. Parsing as an array returns just the one item which essentially is the json as a single entry.
I am not adding any of my code as I believe this would be fruitless, because I have been unable to achieve what I need without errors, and have tried numerous options, all without success.
At the moment your JSON is not valid JSON data. But that might be a typo.
If we change this into valid JSON...
{
"coordinates": [
[
"-0.88676",
"51.47533"
],
[
"-0.88646",
"51.47549"
]
]
}
Then you could represent this as a struct like...
struct Response: Decodable {
let coordinates: [[String]] // <- this is a 2D array of coordinate pairs.
var locations: [CLLocation2D] {
coordinates
.map { $0.compactMap(Double.init) }
.filter { $0.count < 2 }
.map { ($0[0], $0[1]) }
.map(CLLocation2D.init(latitude:longitude:))
} // Something like that anyway
}
Then you can decode it like...
let data = // get the data from the network or a file etc...
let response = JSONDecoder().decode(Response.self, from: data)
That should give you the struct you want.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
The community is reviewing whether to reopen this question as of last year.
Improve this question
JSONDecoder().decode fails when there are commas at the end of a name field. Why is it happening? How can I solve it?
let string = "[{\"name\":\"Homeoffice Marc,\",\"Km\":846.7911330652549,\"Strid\": \"DE262B62633E34AAA8A622E189B42920B319C371\"},{\"name\":\"Küche,\",\"Km\":857.8694764184313,\"Strid\": \"BD1A60D736BE86377121A2CC713251DBE2603BD5\"},{\"name\":\"Besprechungszimmer,\",\"Km\":857.8721480885644,\"Strid\": \"751A10C5D3065F91CC9F5BDF5E7111DC452D1C39\"},{\"name\":\"Büro Vertrieb,\",\"Km\":857.8723091979339,\"Strid\": \"148F97F324BB59EAFF613A0EB3766E026CFAB320\"},{\"name\":\"Büro Produktmanagement und Support,\",\"Km\":857.8734889037903,\"Strid\": \"3A37C955F7D3C012577B1D19B6F662AD233372A5\"},{\"name\":\"Tischkicker,\",\"Km\":857.8748603133218,\"Strid\": \"B5B8A86BBA2102AF56721166D2E814736EF13132\"},{\"name\":\"Büro Entwicklung,\",\"Km\":857.8773683652697,\"Strid\": \"E6814BE03EEF386E63AD7609D970BD9BA8CE71AD\"},{\"name\":\"Syfit GmbH,\",\"Km\":857.877841443768,\"Strid\": \"64F80B1EC04D008E060F28D7F198A8C39DCD53B5\"},{\"name\":\"Büro Zolti,\",\"Km\":857.8798725612223,\"Strid\": \"23F4C2E1C467AEC9D55D873DC3ED7FC73CD92177\"},{\"name\":\"Globale Suche\",\"Km\":null,\"Km\":846.7911330652549}]"
let data = string.data(using: .utf8) ?? Data()
let areas = try? JSONDecoder().decode([AreaModel].self, from: data)
decoding this data returns nil
My model:
struct AreaModel: Codable {
enum CodingKeys: String, CodingKey {
case name
case km = "Km"
case strid = "Strid"
}
let name: String
let km: Double?
let strid: String
}
Please don't ignore thrown errors.
If you can't debug yourself, NEVER USE try?. With more experience, I'd say that we tend to not use try?, but sometimes we do. But when we write try?, we are able to find an possible issue, ie debug if needed.
Let's do a proper try then, with a do/catch:
do {
let areas = try JSONDecoder().decode([AreaModel].self, from: data)
print(areas)
} catch {
print("Error while decoding: \(error)") //and print error, not error.description which is for non-developer and will be missing important information
}
Which should output:
Error while decoding:
keyNotFound(CodingKeys(stringValue: "Strid", intValue: nil),
Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 9", intValue: 9)],
debugDescription: "No value associated with key CodingKeys(stringValue: \"Strid\", intValue: nil) (\"Strid\").", underlyingError: nil))
So, it's the 9th element of your JSON array that causes the issue.
It can't decode properly Strid value. There is no valid String value.
Let's see... You have {"name":"Globale Suche","Km":null,"Km":846.7911330652549}. In fact you have no Strid key here. Did you meant {"name":"Globale Suche","Strid":null,"Km":846.7911330652549}? Even if that's the case it's null, in other words, in Swift it would be nil. So to handle that case, you need to make Strid value optional
let strid: String?
Side note, the start of the answer if taken for another question of mine, so clearly not plagiarism.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I've got a JSON file called 'books.json' looking like this:
{"Books":
[
]
}
and I'd like to add something like this into the array using Go:
{
"Title": "Lord of the Rings",
"Author: "J. R. Tolkien",
"Language: "English"
}
Create a struct to hold your data:
type Book struct {
Title string `json:"Title"`
Author string `json:"Author"`
Language string `json:"Language"`
}
type Library struct {
Books []Book `json:"Books"`
}
Unmarshal existing JSON to the struct:
in := `{"Books": []}`
var library Library
json.Unmarshal([]byte(in), &library)
Append a new Book:
newBook := Book{
Title: "Lord of the Rings",
Author: "J.R. Tolkien",
Language: "English",
}
library.Books = append(library.Books, newBook)
Marshal back to JSON and check the result:
j, _ := json.Marshal(library)
fmt.Println(string(j))
Entire code on Go Playground: https://play.golang.org/p/v24dKorFpK5
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
The new Swift "Decoder" class sounds like a great way to parse JSON data, but all of the examples I've found use a well-known, well-defined 'struct' to do so.
In my case I'm querying an arbitrary website that returns a HUGE JSON string and I only care about a few of the (deeply nested) fields, so I don't want to take all that time to define a 'struct' to get at them.
Is it even possible to do this with "Decoder"? And if so, how does one go about it?
The question seems to be based on a misapprehension about how Decodable works. As a convenience, Decodable is willing to do some automatic code generation behind the scenes so that you can define a struct or nest of structs and just decode the entirety of the JSON. But you are not required to take advantage of that in order to decode JSON.
There is no need to define struct properties for "fields" you don't care about. If a JSON dictionary contains 100 keys and your corresponding struct contains just one property, no problem; that key will be fetched, and no others.
With regard to the "deeply nested" part, it should not take you much time to write simple nested structs that perform the dive to reach the dictionary you really care about. But if you don't want to do even that, you could write an implementation of init(from:) that dives down and fetches out the desired values.
In other words, if you think of Decodable as consisting primarily of your implementation of init(from:), and learn to write the code that it needs, you will see that this JSON can be parsed in a few quick simple lines of code.
As an example, here's a JSON sketch of a deeply nested piece of information with a bunch of extra information at every level that we want to ignore:
{
"ignore": true,
"outer1": {
"ignore": true,
"outer2": {
"ignore": true,
"outer3": {
"name": "matt",
"ignore": true
}
}
}
}
What I'd like to do is define a very simple struct Person that consists solely of the deeply nested name:
struct Person : Decodable {
let name : String
}
I can do that! To do so, I implement Decodable myself, supplying a "hoover" CodingKey adopter struct and an implementation of init(from:), like this (this may look like a lot of work, but it isn't, because the AnyCodingKey implementation is boilerplate, copied and pasted from here, and the init(coder:) implementation is just a few lines of code that were easy to write):
struct Person : Decodable {
let name : String
struct AnyCodingKey : CodingKey {
var stringValue: String
var intValue: Int?
init(_ codingKey: CodingKey) {
self.stringValue = codingKey.stringValue
self.intValue = codingKey.intValue
}
init(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}
init(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
init(from decoder: Decoder) throws {
var con = try! decoder.container(keyedBy: AnyCodingKey.self)
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer1"))
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer2"))
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer3"))
let name = try! con.decode(String.self, forKey: AnyCodingKey(stringValue:"name"))
self.name = name
}
}
When I want to dive into the JSON and grab the name information, it's trivial:
let person = try! JSONDecoder().decode(Person.self, from: json)
The result is a Person object with name value "matt". Note that I didn't have to add any of the ignore keys and I didn't need to make a nest of structs.
Sure you can achieve this but with both JSonSerialization & Decodable , you have to serialize the json until reach the desired content then decode it ,but instead I recommend to create structs for root keys only then decode , think of it as it's a path from top to bottom don't decode a key that isn't in the path of your desired content
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I am receiving JSON text, converting it to Data, and then using JSONDecoder to create a concrete type represented by the JSON text/string.
It does work with my "complex" data structure (which implements Codable), or even a simple array of Int as shown below:
import Foundation
let jsonTextContainigArrayOfInt: String = "[1,2,3]"
let data = jsonTextContainigArrayOfInt.data(using: .utf8)!
do {
let arrayOfInt: [Int] = try JSONDecoder().decode([Int].self, from: data)
for n in arrayOfInt {
print(n)
}
}
catch {
print(error)
}
The previous code works and correctly creates the array of Int and prints them.
The problem occurs when doing this same approach with a single Int in the JSON-text:
import Foundation
let jsonTextContainigOneInt: String = "1"
let data = jsonTextContainigOneInt.data(using: .utf8)!
do {
let myInt: Int = try JSONDecoder().decode(Int.self, from: data)
print(myInt)
}
catch {
print(error)
}
For this second approach, I get the following error:
"The operation could not be completed"
*** Edit ***
Bug report for this already exists: https://bugs.swift.org/browse/SR-6163
JSONDecoder can only decode a collection type (array or dictionary) as root object.
Under the hood JSONDecoder uses JSONSerialization without any options. However to decode a String or Int you have to specify the .allowFragments option.
Use JSONSerialization with the .allowFragments option
let jsonTextContainingOneString = "1"
let data = Data(jsonTextContainingOneString.utf8)
do {
let myString = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(myString)
}
catch {
print(error)
}
Interesting... I found this:
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/JSONSerialization.swift#L120
Specifically this guard statement:
open class JSONSerialization : NSObject {
//...
// top level object must be an Swift.Array or Swift.Dictionary
guard obj is [Any?] || obj is [String: Any?] else {
return false
}
//...
}
Then I looked if a simple text-string should be considered valid JSON, and apparently it should now (it was previously not accepted as valid JSON). At least, based on this excellent answer: https://stackoverflow.com/a/7487892/8284660
This makes me wonder whether or not the behavior on my original post should be a bug or not.