JSON Deserialization in Swift - json

After reading up a bit on collections, I began to wonder if json deserialization was going to be an issue given that collections need to specify a type for the values they contain. And in the case of dictionaries, one would need to specify the type for both the key and the value.
After a bit of experimentation, I found that the following works:
let jsonString = "{\"bool\": true, \"num\": 1,\"string\": \"a string\"}"
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let json : AnyObject! = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
let valid = NSJSONSerialization.isValidJSONObject(json)
And when I use a playground (or am in the REPL), I get the following when printing out the contents of the json object:
["num": 1, "string": "a string", "bool": 1]
My question: is there may be a better way to handle this?

I'd suggest typing your json object a little more:
let json = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as? Dictionary<String, AnyObject?>
This will help you access elements by their key.

Related

Parse a String (of array of strings) in JSON to an array of Strings in Swift

Does Swift provide a way to convert a raw String like this
"[\"John\",\"Anna\",\"Tom\"]"
to an Array of strings ([String])?
I've looked for a way to do it over StackOverflow, but in that specific way, I could not find an answer :/
On Swift 4 and later, use JSONDecoder:
let rawString = "[\"John\",\"Anna\",\"Tom\"]"
let jsonData = rawString.data(using: .utf8)!
let strings = try JSONDecoder().decode([String].self, from: jsonData)
Code Different answer is probably a recommended way to do it nowadays (Swift 4+).
For reference, here is a classic way to do the same, compatible with older Swift versions:
let rawString = "[\"John\",\"Anna\",\"Tom\"]"
let jsonData = rawString.data(using: .utf8)!
let strings = (try? JSONSerialization.jsonObject(with: jsonData, options: [])) as? [String] ?? []
According to Itai Ferber, JSONDecoder uses JSONSerialization under the hood, so it should do pretty much the same as Code Different answer.

How do I decode a JSON file containing arrays Swift 4?

I have a JSON file which I'm trying to decode but am getting an error message:
typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected to decode Dictionary but found an array instead.", underlyingError: nil))
My code is as follows:
struct Phrase: Decodable {
let sentences: [String]
}
func getFromJSON() {
do {
let jsonURL = Bundle.main.url(forResource: "script", withExtension: "json")
let jsonDecoder = JSONDecoder()
let jsonData = try Data(contentsOf: jsonURL!)
let jsonSentence = try jsonDecoder.decode([Phrase].self, from: jsonData)
debugPrint(jsonSentence)
} catch {
print(error)
}
}
I've been looking at lots of other stack overflow questions and I've noticed that the format of these JSON files are different to mine. They are formatted as dictionaries while mine is like this-
[
["bin blue", "with A 2 soon"],
["set blue", "in A 9 soon"],
["lay blue", "at A 3 please"],
["3 5 zero zero 5 8"],
["place blue", "by A 6 now"],
["lay green", "at B ZERO now"],
["8 9 1 5 4 zero"]
]
I know that the decoder is looking for a dictionary but how do I have it decode the arrays instead?
I think you need
let jsonSentence = try jsonDecoder.decode([[String]].self, from: jsonData)
Your JSON data does not match the structure you want to parse. The JSON is an array of string arrays, whereas you try to parse an array of Phrase objects.
Solution 1: to keep the JSON structure as-is, you need to parse an array of arrays, or to keep the custom model type, by using a type alias:
typealias Phrase = [String]
Solution 2: to keep the struct you defined as-is, you'll have to change the JSON format to this;
[
{ "sentences": ["bin blue", "with A 2 soon"] },
{ "sentences": ["set blue", "in A 9 soon"] },
...
]
Both solutions will work with your getFromJSON implementation.

Swift - Convert [[String:Any?]] to Data

I have an [[String:Any]] object populated like:
var result : [[String : Any]] = [[String : Any]]()
And I need convert it to Data.
I'm just using:
JSONEncoder().encode(result)
To convert it.
But I get this error:
Generic parameter 'T' could not be inferred
Exist a simple way to convert a [[String:Any?]] object toData` ?
JSONEncoder can only encode objects whose type conforms to Encodable. If you want to encode Any to JSON, you need to use JSONSerialization to do that.
let jsonData = try? JSONSerialization.data(withJSONObject:result)
You can also using struct for that and using
let data = try? JSONEncoder().encode(struct_Object))

Find values from JSON with unknown structure SWIFT

I read some questions about parsing JSON with unknown strucutre. But these questions are not in Swift and don't solve my issue.
I have a big JSON file that I obtain with a Alamofire HTTP request. Here is it: https://pastebin.com/Y7cWSWAt
In fact, the JSON could change with requests I do. It will not always be the same structure depending of the user (for example). However, there will be the same keys and values.
So I know the keys in the JSON to find the values, their will be always the same. But I don't know how to access them. Moreover, my JSON has an Any type (I can't give him a specific type because I don't know it).
My question: Is there a solution to find values with this? Can I loop throw all the JSON values to find specific keys and values? Is it better to work with JSON file or Dictionaries? I have no code yet because I have no idea. Thanks mates!
if you want to use just NSDictionary this not problem but when return array json your app will be crash because variable type not be equals.
let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)
if json != nil {
let obj = json as? NSDictionary
}
//this part write all key and value
for (key, value) in obj {
print("Property: \"\(key as String)\", Value: \"\(value as String)\"")
}
input: {"test1":"value1","test2":"value2"}
output:
Property: "test1", Value: "value1"
Property: "test2", Value: "value2"

Swift 2.0 How to parse JSON?

I am coding a hangman game and am loading the possible words into my app using json text files. I tried to follow the examples of others on this website but I am getting errors from Xcode.
I tried the following code based on another answer:
import Foundation
var error: NSError?
let jsonData: NSData = /* get your json data */
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
But I got an errors on line 4 with jsonDict that said "call can throw but is not marked with try, and the error is not handled" and "Type JSONReadingOptions does not conform to protocol NilLiteralConvertible".
Here is the JSON File I would like to parse:
{
“wordList” : {
“difficulty” : “Easy”
“list” : [
“fireplace”,
“apple”,
“january”,
“tooth”,
“cookies”,
“mysterious”,
“essential”,
“magenta",
“darling”,
“pterodactyl”
]}}
I would like to be able to go into my list array and get values. Thank you very much for any help!
In Swift 2 you need to use the new error handling API instead of passing a reference to an NSError:
do {
let jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary
if let jsonDict = jsonDict {
// work with dictionary here
} else {
// more error handling
}
} catch let error as NSError {
// error handling
}
You also can't pass nil as value to the options parameter, you need to pass a value of type NSJSONReadingOptions.
That said, the most common approach for parsing JSON in Swift is currently using third party libraries, such as Argo because they can save you a lot of code that is necessary to validate and safely cast the content of your JSON data to the correct Swift types.