Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
734 views
in Technique[技术] by (71.8m points)

xcode - JSON Parsing in Swift 3

Has anyone been able to find a way to parse through JSON files in Swift 3? I have been able to get the data to return but I am unsuccessful when it comes to breaking the data down into specific fields. I would post sample code but I've gone through so many different methods unsuccessfully and haven't saved any. The basic format I want to parse through is something like this. Thanks in advance.

{
  "Language": {

    "Field":[
          {
          "Number":"976",
          "Name":"Test"
          },
          {
          "Number":"977",
          "Name":"Test"
          }
       ]
   }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Have you tried JSONSerialization.jsonObject(with:options:)?

var jsonString = "{" +
    ""Language": {" +
    ""Field":[" +
    "{" +
    ""Number":"976"," +
    ""Name":"Test"" +
    "}," +
    "{" +
    ""Number":"977"," +
    ""Name":"Test"" +
    "}" +
    "]" +
    "}" +
    "}"

var data = jsonString.data(using: .utf8)!

let json = try? JSONSerialization.jsonObject(with: data)

Swift sometimes produces some very odd syntax.

if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
    print(number)
}

Everything in the JSON object hierarchy ends up getting wrapped as an optional (ie. AnyObject?). Array<T> subscript returns a non-optional T. For this JSON, which is wrapped in an optional, array subscript returns Optional<AnyObject>. However, Dictionary<K, V> subscript returns an Optional<V>. For this JSON, subscript returns the very odd looking Optional<Optional<AnyObject>> (ie. AnyObject??).

  • json is an Optional<AnyObject>.
  • json?["Language"] returns an Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"] returns an Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0] returns an Optional<AnyObject>.
  • json?["Language"]??["Field"]??[0]?["Number"] returns an Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0]?["Number"] as? String returns an Optional<String>.

The Optional<String> is then used by the if let syntax to product a String.


Final note: iterating the field array looks like this.

for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
    if let number = field["Number"] as? String {
        print(number)
    }
}

Swift 4 Update

Swift 4 makes this all much easier to deal with. Again we will start with your test data (""" makes this so much nicer).

let data = """
{
  "Language": {

    "Field":[
          {
          "Number":"976",
          "Name":"Test"
          },
          {
          "Number":"977",
          "Name":"Test"
          }
       ]
   }
}
""".data(using: .utf8)!

Next we can define classes around the objects used in your JSON.

struct Object: Decodable {
    let language: Language
    enum CodingKeys: String, CodingKey { case language="Language" }
}

struct Language: Decodable {
    let fields: [Field]
    enum CodingKeys: String, CodingKey { case fields="Field" }
}

struct Field: Decodable {
    let number: String
    let name: String
    enum CodingKeys: String, CodingKey { case number="Number"; case name="Name" }
}

The CodingKeys enum is how struct properties are mapped to JSON object member strings. This mapping is done automagically by Decodable.


Parsing the JSON now is simple.

let object = try! JSONDecoder().decode(Object.self, from: data)

print(object.language.fields[0].name)

for field in object.language.fields {
    print(field.number)
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...