简体   繁体   中英

Swift 3 - How to convert an array of structs that contain structs to JSON?

I have an array of Field structs that I want to convert to a JSON string.

Field is defined as:

struct Field{

    var name: String
    var center: LatLng
    var perimeter: [LatLng]

    func toDictionary() -> [String : Any]{
        let dict: [String : Any] = ["name":self.name, 
                                    "center":self.center.toDictionary(),
                                    "perimeter": ppsToDictArray()]
        return dict
    }

    fileprivate func ppsToDictArray() -> [Any]{
        var data = [Any]()
        for pp in perimeterPoints{
            data.append(pp.toDictionary())
        }
        return data
    }


}

and LatLng is defined as:

struct LatLng{

    let latitude: Double
    let longitude: Double

    func toDictionary() -> [String : Any]{
        let dict: [String : Any] = ["latitude": self.latitude,
                                    "longitude": self.longitude]
        return dict
    }

}

Here's where I'm trying to convert my array to JSON:

    //selectedFields is a [Field] populated with some Fields
    let dicArray = selectedFields.map{$0.toDictionary()}
    if let data = try? JSONSerialization.data(withJSONObject: dicArray, options: .prettyPrinted){
        let str = String(bytes: data, encoding: .utf8)
        print(str) //Prints a string of "\n\n"
    }

How can I convert such and array to a JSON string? I attempted something along the lines of this answer , but it prints as Optional("[\\n\\n]")" (I understand why it says "Optional" when printing). I can't seem to get it to work after extrapolating for my structs-within-structs situation. I'm also only about a month into Swift.

EDIT: I edited the above code to represent a more complete example of what I was working on in response to a request to see more work. I didn't include all of that originally because I wasn't asking how to fix my existing code, but more for an example of how to go about the process with nested structs.

struct LatLng {
    let latitude: Double
    let longitude: Double

    func getJSON() -> NSMutableDictionary {
        let dict = NSMutableDictionary()
        dict.setValue(latitude, forKey: "latitude")
        dict.setValue(longitude, forKey: "longitude")
        return dict
    }
}

struct Field {
    var name: String
    var center: LatLng
    var perimeter: [LatLng]

    func getJSON() -> NSMutableDictionary {
        let values = NSMutableDictionary()

        var perimeterArray = Array<NSMutableDictionary>()
        for item in perimeter {
            perimeterArray.append(item.getJSON())
        }

        values.setValue(name, forKey: "name")
        values.setValue(center.getJSON(), forKey: "center")
        values.setValue(perimeterArray, forKey: "perimeter")

        return values

    }
}

let peri = [LatLng(latitude: 10.0, longitude: 10.0), LatLng(latitude: 20.0, longitude: 20.0)]
let center = LatLng(latitude: 15.0, longitude: 15.0)

let field = Field(name: "test", center: center, perimeter: peri)

let json = try NSJSONSerialization.dataWithJSONObject(field.getJSON(), options: .PrettyPrinted)
let jsonString = NSString(data: json, encoding: NSUTF8StringEncoding)
print(jsonString)

//PRINTS THE FOLLOWING OUTPUT
Optional({
    "name" : "test",
    "center" : {
        "longitude" : 15,
        "latitude" : 15
    },
    "perimeter" : [{
        "longitude" : 10,
        "latitude" : 10
    },
    {
        "longitude" : 20,
        "latitude" : 20
    }]
})

UPDATE

In order to serialise an array of Field objects, you can do something like this.

let field1 = Field(name: "value1", center: center, perimeter: peri)
let field2 = Field(name: "value2", center: center, perimeter: peri)
let field3 = Field(name: "value3", center: center, perimeter: peri)

let fieldArray = [field1.getJSON(), field2.getJSON(), field3.getJSON()]

let json = try NSJSONSerialization.dataWithJSONObject(fieldArray, options: .PrettyPrinted)
let jsonString = NSString(data: json, encoding: NSUTF8StringEncoding)

Please note that this is just a quick solution, not the best one. This is just to give you an idea of how it will go. I'm sure you'll be able to improve on it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM