How do you create a SwiftyJSON dictionary out of optional AnyObjects? - json

I recently ran into a very time-consuming issue for a simple task of creating a JSON dictionary with optional objects. I'm using SwiftyJSON.
If I create the following dictionary, I get thrown errors
JSON type doesn't have an initializer that supports Dictionary<String,AnyObject?>
But if I simply change AnyObject to an non-optional type, it works.
var dict: Dictionary <String, AnyObject?> = [
"title" : title as? AnyObject,
"date" : date as? AnyObject,
]
var jsonData: JSON = JSON(dict) // this is where I get the error
I need to actually a JSON data set that potentially has nil values, but it seems like SwiftyJSON doesn't allow it.
Is there any way I can create a JSON dictionary with optional objects using SwiftyJSON?

Neither any key nor any value of a Swift Dictionary can be nil.
You could declare the variable as optional
var dict: Dictionary <String, AnyObject>?

Related

Empty dictionary are encoded to empty JSON arrays if key is UUID

I'm trying to encode/decode JSON with Swift's JSONEncoder/Decoder. My JSON contains a dictionary with UUID as Key. If this dictionary is empty, Swift fails with
Expected to decode Array<Any> but found a dictionary instead.
While analyzing I noticed, that Swift creates different repressions of the empty dictionary depending on the key's type. The following minimum example illustrates the problem quite well:
import Foundation
typealias Key = UUID // or String
struct Foo: Codable {
let data: [Key: String]
}
let foo = Foo(data: [:])
let encodedData = try JSONEncoder().encode(foo)
let foo2 = try JSONDecoder().decode(Foo.self, from: encodedData)
print(String(decoding: encodedData, as: UTF8.self))
When using UUID as key's type you get:
{"data":[]}
and when using String as key's type you get:
{"data":{}}
I'd expect {"data":{}} in all cases. What I'm doing wrong here?

Elm: decode local JSON file into dict

I'm working on my first Elm app.
I want to use a local JSON file as a lookup table. The file matches weather conditions (a string) to suggested clothing (a list).
EDIT (clarifying the question): Based on some earlier SO questions from 2015 I've tried using Http.get to get the contents and then Decode.dict to create the Dict. It seems strange to use an Http module to ingest a local file. Is this methodology, including the Http.send I use below correct in Elm?
I am also having a hard time finding an example of a decoder that would work for a JSON file like the one I have. Any pointers would be appreciated.
JSON
{
"male,10,overcast,light wind...": ["Winter Cap", "Light Jacket"...],
"female,30,partly cloudy...": ["Winter Cap", "Sunglasses", ...]
}
CODE
type alias ClothingDict =
Dict String List
clothingUrl: String
clothingUrl =
"./clothing.json"
getClothingDict : Cmd Msg
getClothingDict =
let
url = clothingUrl
in
Http.send SetClothing (Http.get url decodeClothingResponse)
type alias ClothingResponse =
{ clothingOptions: ClothingDict }
decodeClothingResponse : Decoder ClothingResponse
decodeClothingResponse =
Decode.dict ClothingResponse
Decode.dict or dict takes a Decoder in order to handle decoding the keys of the Dict. dict automatically extracts the keys as strings.
I converted the code to:
decodeClothingResponse : Decoder (Dict String (List String))
decodeClothingResponse =
dict (list string)
(list string) is a decoder that will decoder a list of string from json in to a List String

Reading JSON output in Swift

I am trying to read a JSON output from a web app. This output is:
[{"group_name":"XYZ","adminof":0}]
I have a struct that looks like:
struct grouplistStruct{
var group_name : String
var adminof : Any
}
The code that I am using is:
let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as! [Any]
for jsonResult in jsonArray{
let loc = grouplistStruct(group_name: jsonResult["group_name"], adminof: jsonResult["adminof"])
I can see that jsonArray reads the value correctly. Similarly in the for loop, jsonResult is also reading the value correctly
But when I try to assign this value to a Struct variable, it shows an error:
Type 'Any' has no subscript members
Why is that happening? Sorry I am new to Swift so I am learning all this.
Since your json data is an array containing dictionaries like this:
[{"group_name":"XYZ","adminof":0}]
You are getting the error
Type 'Any' has no subscript members
because you are downcasting the json as an array of Any and in swift Any (as the name suggests) represents any type like Int, Double or Dictionary of type [String: String] as you know that Int or Double can not have subscript like someInt["subscript"]
So you need to downcast to this specific type using [[String: Any]] .
This represents an array containing the dictionaries of type [String: Any]. This will work because dictionaries can have subscript members e.g someDict["group_name"]
Hence you should use [[String: Any]] instead of [Any] in this statement try JSONSerialization.jsonObject(with: data, options: []) as! [Any]

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 remove optional from Dictionary of Dictionary

I'm taking data from an api in the form of JSON. I get a variable of dynamicType Swift.Dictionary<NSObject, Swift.AnyObject> and call this variable myDictionary. When I ask for print(myDictionary["keyA"]) it returns the value (inner dictionary) associated with "keyA", but it returns it as a Swift.Optional<Swift.AnyObject>.
How do I set a variable with the inner dictionary that isn't optional? Or how to I access the inner dictionary values?
All dictionary accesses are returned as optionals because the key used might not exist in the dictionary, and thus nil is returned in that case. You can use optional casting as? along with optional binding if let to make sure the value exists, that it is a dictionary as expected, and unwrap it:
if let innerDictionary = myDictionary["keyA"] as? [NSObject: AnyObject] {
// if we get here, "keyA" is a valid key in myDictionary and
// we got the type right. innerDictionary is now unwrapped and ready
// to use.
}
I used [NSObject: AnyObject] as the innerDictionary type. If you know more about it, you can use a more specific cast, for example as? [String: String] if you know that both keys and values are of type String. If you are wrong, the optional cast will return nil and the block will not be entered because the optional binding will not succeed.