从JSON中提取对象为字符串在Swift中。

huangapple go评论58阅读模式
英文:

Extract object as string from JSON in Swift

问题

{
    "identifier": "{\"channel\":\"SomeChannel\"}",
    "message": {
        "resource": {
            "owner_id": 1,
            "name": "Some cool name",
            "id": 2,
            "field1": "Example field",
            "fieldTwo": { "name": "Nested object" },
            "fieldXYZ": 123321,
            "created_at": "2022-11-27T22:13:51.429Z",
            "updated_at": "2023-06-18T18:50:11.738Z"
        },
        "action": "replace",
        "kind": "Foo"
    }
}

Swift 代码示例:

action = "replace"
kind = "Foo"
resource = """
  {
    "owner_id": 1,
    "name": "Some cool name",
    "id": 2,
    "field1": "Example field",
    "fieldTwo": { "name": "Nested object" },
    "fieldXYZ": 123321,
    "created_at": "2022-11-27T22:13:51.429Z",
    "updated_at": "2023-06-18T18:50:11.738Z"
  }
"""
英文:

I have a WebSocket connection in Swift which will give me the following JSON:

{
    "identifier": "{\"channel\":\"SomeChannel\"}",
    "message": {
        "resource": {
            "owner_id": 1,
            "name": "Some cool name",
            "id": 2,
            "field1": "Example field",
            "fieldTwo": { "name": "Nested object" },
            "fieldXYZ": 123321,
            "created_at": "2022-11-27T22:13:51.429Z",
            "updated_at": "2023-06-18T18:50:11.738Z"
        },
        "action": "replace",
        "kind": "Foo"
    }
}

The resource here is dynamic and changing, depending on the value in the kind field. So I am trying to write a method which will return something like this:

action = "replace"
kind = "Foo"
resource = """
  {"owner_id":1, "name":"Some cool name", "id": 2,
   "field1": "Example field", "fieldTwo": { "name": "Nested object" }, ... }
"""

This would help me decode the resource and take the appropriate action. But I cannot figure out how to turn message.resource into a string which works for any kind of content in that field.

答案1

得分: 1

以下是翻译好的部分:

一种解决方法是将JSON转换为字典(而不是对象),然后导航到所需的结果。

以下代码有5个步骤:

  1. 将JSON转换为字典
  2. 将消息转换为字典
  3. 将资源转换为字典并对其进行序列化(然后您会得到一个String
  4. 构建输出

请记住处理所有的可选项 - 在这个示例中,我已经强制解包了它们。

    let json = """
{
"identifier": {"channel":"SomeChannel"},
"message": {
    "resource": {
        "owner_id": 1,
        "name": "Some cool name",
        "id": 2,
        "field1": "Example field",
        "fieldXYZ": 123321,
        "created_at": "2022-11-27T22:13:51.429Z",
        "updated_at": "2023-06-18T18:50:11.738Z"
    },
    "action": "replace",
    "kind": "Foo"
}
}
"""
    
    // 1. 将JSON转换为字典
    let data = json.data(using: .utf8)! // 这一行不需要翻译
    let dict = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] // 这一行不需要翻译
    
    // 2. 将消息转换为字典
    let message = dict["message"]! as! [String: Any] // 这一行不需要翻译

    // 3. 将资源转换为字典并序列化它(然后您会得到一个`String`)
    let resourceDict = try! JSONSerialization.data(withJSONObject: message["resource"]!) // 这一行不需要翻译
    let resourceString = String(bytes: resourceDict, encoding: .utf8) // 这一行不需要翻译
    
    //  4. 构建输出
    let result = [message["action"]! as! String, message["kind"]! as! String, resourceString] // 这一行不需要翻译
    
    print(result) // 这一行不需要翻译
    /* ["replace",
        "Foo",
        "{\"updated_at\": \"2023-06-18T18:50:11.738Z\",
          \"field1\": \"Example field\",
          \"fieldTwo\": { \"name\": \"Example field\" },
          \"created_at\": \"2022-11-27T22:13:51.429Z\",
          \"fieldXYZ\": 123321,
          \"name\": \"Some cool name\",
          \"id\": 2,
          \"owner_id\": 1}"
       ]
     */
英文:

One solution is to convert the JSON into a dictionary (instead of an object), and then make your way to the desired result.

The code below has 5 steps:

  1. Convert the JSON to a dictionary
  2. Cast the message to a dictionary
  3. Cast the resource to a dictionary and serialize it (then you have a String)
  4. Build the output

Remember to handle all the optionals - I have force-unwrapped them in this example.

    let json = """
{
"identifier": {"channel":"SomeChannel"},
"message": {
    "resource": {
        "owner_id": 1,
        "name": "Some cool name",
        "id": 2,
        "field1": "Example field",
        "fieldXYZ": 123321,
        "created_at": "2022-11-27T22:13:51.429Z",
        "updated_at": "2023-06-18T18:50:11.738Z"
    },
    "action": "replace",
    "kind": "Foo"
}
}
"""
    
    // 1. Convert the JSON to a dictionary
    let data = json.data(using: .utf8)!
    let dict = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
    
    // 2. Cast the message to a dictionary
    let message = dict["message"]! as! [String: Any]

    // 3. Cast the resource to a dictionary and serialise it (then you have a `String`)
    let resourceDict = try! JSONSerialization.data(withJSONObject: message["resource"]!)
    let resourceString = String(bytes: resourceDict, encoding: .utf8)
    
    //  4. Build the output
    let result = [message["action"]! as! String, message["kind"]! as! String, resourceString]
    
    print(result)
    /* ["replace",
        "Foo",
        "{\"updated_at\": \"2023-06-18T18:50:11.738Z\",
          \"field1\": \"Example field\",
          \"fieldTwo\": { \"name\": \"Example field\" },
          \"created_at\": \"2022-11-27T22:13:51.429Z\",
          \"fieldXYZ\": 123321,
          \"name\": \"Some cool name\",
          \"id\": 2,
          \"owner_id\": 1}"
       ]
     */

答案2

得分: 0

你想要一种奇怪的格式,但可以。
你可以使用 JSONSerialization 来实现,并使用它将 resource 返回为 JSON 字符串...

do {
    let decodedJSON = try JSONSerialization.jsonObject(with: Data(jsonStr.utf8))
    guard let dict = decodedJSON as? [String: Any],
          let message = dict["message"] as? [String: Any] else { return }
    var content: [String] = []
    if let action = message["action"] as? String {
        content.append("action = \"\(action)\"")
    }
    if let kind = message["kind"] as? String {
        content.append("kind = \"\(kind)\"")
    }
    if let resource = message["resource"], let resourceJSONData = try? JSONSerialization.data(withJSONObject: resource), let resourceJSONStringified = String(data: resourceJSONData, encoding: .utf8) {
        content.append("resource = \"\"\"\n\(resourceJSONStringified)\n\"\"\"")
    }
    let output = content.joined(separator: "\n")
    print(output)
} catch {
    print("Error: \(error)")
}

输出:

action = "replace"
kind = "Foo"
resource = """
{"field1":"Example field","id":2,"created_at":"2022-11-27T22:13:51.429Z","fieldXYZ":123321,"fieldTwo":{"name":"Nested object"},"updated_at":"2023-06-18T18:50:11.738Z","owner_id":1,"name":"Some cool name"}
"""
英文:

You want a strange format, but fine.
You can use JSONSerialization for that, and use it to get back resource as JSON String...

do {
    let decodedJSON = try JSONSerialization.jsonObject(with: Data(jsonStr.utf8))
    guard let dict = decodedJSON as? [String: Any],
          let message = dict["message"] as? [String: Any] else { return }
    var content: [String] = []
    if let action = message["action"] as? String {
        content.append("action = \"\(action)\"")
    }
    if let kind = message["kind"] as? String {
        content.append("kind = \"\(kind)\"")
    }
    if let resource = message["resource"], let resourceJSONData = try? JSONSerialization.data(withJSONObject: resource), let resourceJSONStringified = String(data: resourceJSONData, encoding: .utf8) {
        content.append("resource = \"\"\"\n\(resourceJSONStringified)\n\"\"\"")
    }
    let output = content.joined(separator: "\n")
    print(output)
} catch {
    print("Error: \(error)")
}

Output:

action = "replace"
kind = "Foo"
resource = """
{"field1":"Example field","id":2,"created_at":"2022-11-27T22:13:51.429Z","fieldXYZ":123321,"fieldTwo":{"name":"Nested object"},"updated_at":"2023-06-18T18:50:11.738Z","owner_id":1,"name":"Some cool name"}
"""

huangapple
  • 本文由 发表于 2023年6月19日 05:05:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502518.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定