Swift: найдите ключ json и отредактируйте его - PullRequest
1 голос
/ 05 августа 2020

Я пишу, потому что мне нужно найти json -ключ, переданный в функции, такой как строка. Есть ли у вас какие-нибудь предложения, как я могу это реализовать? Как только я найду ключ, мне также нужно будет отредактировать значение. Вот код, который я написал до сих пор:

JSON:

{
    "JSONRoot": {
        "version": 1,
        "Town": {
            "hour": 0,
            "latitude": "",
            "longitude": 0,
            "latitudine": 0
        },
        "MeasurePoints": {
            "MeasurePoint": [
                {
                    "code": "",
                    "codelocation": "",
                }
            ]
        },
        "Wakeup": {
            "startH": 6,
            "startM": 0,
            "maxAttempts": 3,
            "maxRetry": 10
        },
        "Config": {
            "port": 12345,
            "A": {
                "writable": true,
                "value": 12
            },
            "B": {
                "writable": true,
                "value": 8
            },
        },
        "Sales": {
            "Stores": {
                "Store": [
                    {
                        "description": "A description",
                        "type": "1",
                        "Floors": {
                            "basement": true,
                            "number": 2
                        },
                        "Doors": {
                            "type": "",
                            "number": 7
                        },
                        "Lights": {
                            "number": 20
                        }
                    },
                    {
                        "description": "A description",
                        "type": "4",
                        "Floors": {
                            "basement": none,
                            "number": 1
                        },
                        "Doors": {
                            "type": "",
                            "number": 4
                        },
                        "Lights": {
                            "number": 8
                        }
                    }
                ]
            }
        }
    }
}

Структуры с возможностью кодирования:

// MARK: - JSONConfig
struct JsonConfig: Codable {
    let jsonRoot: JSONRoot?

    enum CodingKeys: String, CodingKey {
    case jsonRoot = "JSONRoot"
    }
}

// MARK: - JSONRoot
struct JSONRoot: Codable {
    let version: Int?
    let measurePoints: MeasurePoints?
    let wakeup: Wakeup?
    let config: Config?
    let sale: Sale?

    enum CodingKeys: String, CodingKey {
        case version
        case measurePoints = "MeasurePoints"
        case wakeup = "Wakeup"
        case config = "Config"
        case sale = "Sale"
    }
}

// MARK: - Stores
struct Stores: Codable {
    let stores: [Store]?

    enum CodingKeys: String, CodingKey {
    case stores = "Stores"
    }
}

// MARK: - Store
struct Store: Codable {
    let storeDescription: String?
    let type: Int?
    let floors: Floors?
    let doors: Doors?
    let lights: Lights?

    enum CodingKeys: String, CodingKey {
    case storeDescription = "description"
        case type
        case floors = "Floors"
        case doors = "Doors"
        case lights = "Lights"
    }
}

// MARK: - Floors
struct Floors: Codable {
    let basement: Bool?
    let number: Int?
}

// MARK: - Doors
struct Doors: Codable {
    let type: String?
    let number: Int?
}

// MARK: - Lights
struct Lights: Codable {
    let number: Int?
}

// MARK: - MeasurePoints
struct MeasurePoints: Codable {
    let measurePoint: [MeasurePoint]?

    enum CodingKeys: String, CodingKey {
        case measurePoint = "MeasurePoint"
    }
}

// MARK: - MeasurePoint
struct MeasurePoint: Codable {
    let code, codeLocation: String?
}

// MARK: - Config
struct Config: Codable {
    let port: Int?
    let a, b: K?

    enum CodingKeys: String, CodingKey {
        case port
        case a = "A"
        case b = "B"
    }
}

// MARK: - K
struct K: Codable {
    let writable: Bool?
    let value: Int?
}

// MARK: - Wakeup
struct Wakeup: Codable {
    let startH, startM, maxAttempts, maxRetry: Int?
}

Функция для поиска ключа:

func setKeyValue(jsonKey: String, value: String) {
  let decoder = JSONDecoder()

  let jsonData = Data(C.jsonString.utf8)

  if let jsonResult = try? decoder.decode(JsonConfig.self, from: jsonData) {

    // At this point I have the jsonKey = "JSONRoot.Wakeup.maxRetry" but how I can use it to search for
    // the key in the jsonResult?
    
  }
}

Очевидно, мне нужно создать новую структуру для редактирования json, но по одному шагу за раз.

Ответы [ 3 ]

1 голос
/ 06 августа 2020

Использование JSONSerialisation, вероятно, самый простой способ здесь

var value: Any?
do {
    if let jsonResult = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
        let keys = "JSONRoot.Wakeup.maxRetry".split(separator: ".").map {String($0)}

        var dict = jsonResult
        for i in 0..<keys.count {
            if let temp = dict[keys[i]] as? [String:Any] {
                dict = temp
                continue
            }
            value = dict[keys[i]]
        }
    }
} catch {
    print(error)
}

Обратите внимание, что это не поддерживает массивы, но решение для этого очень зависит от того, как синтаксис ключа поиска будет обрабатывать массив

0 голосов
/ 05 августа 2020

Если я думаю так же, как и вы, вы можете попробовать этот код.

override func viewDidLoad() {
    super.viewDidLoad()
    
    let jsonString = """
{
    "JSONRoot": {
        "version": 1,
        "Town": {
            "hour": 0,
            "latitude": "",
            "longitude": 0,
            "latitudine": 0
        },
        "MeasurePoints": {
            "MeasurePoint": [{
                "code": "",
                "codelocation": ""
            }]
        },
        "Wakeup": {
            "startH": 6,
            "startM": 0,
            "maxAttempts": 3,
            "maxRetry": 10
        },
        "Config": {
            "port": 12345,
            "A": {
                "writable": true,
                "value": 12
            }
        },
        "Sales": {
            "Stores": {
                "Store": [{
                        "description": "A description",
                        "type": "1",
                        "Floors": {
                            "basement": true,
                            "number": 2
                        },
                        "Doors": {
                            "type": "",
                            "number": 7
                        },
                        "Lights": {
                            "number": 20
                        }
                    },
                    {
                        "description": "A description",
                        "type": "4",
                        "Floors": {
                            "basement": "none",
                            "number": 1
                        },
                        "Doors": {
                            "type": "",
                            "number": 4
                        },
                        "Lights": {
                            "number": 8
                        }
                    }
                ]
            }
        }
    }
}
"""
    
    
    editJson(jsonString)
}


func editJson(_ jsonString: String) {
    do{
        let jsonData = Data(jsonString.utf8)
        var jsonObject = try JSONSerialization.jsonObject(with: jsonData)
        parseDict(&jsonObject)
        print("jsonObject: \(String(describing: jsonObject))")
    }catch let error {
        print(error.localizedDescription)
    }
}

func parseDict(_ jsonObject: inout Any) {
    if let _ = jsonObject as? String {
        return
    } else if var dictionary = jsonObject as? Dictionary<String, Any> {
        for (key, value) in dictionary {
            var nextObject = value
            parseDict(&nextObject)
            if let value = getValueWith(key), let _ = dictionary.removeValue(forKey: key) {
                dictionary[key] = value
            } else {
                dictionary[key] = nextObject
            }
        }
        jsonObject = dictionary
    }else if let array = jsonObject as? Array<Any> {
        var updatedArray = array
        for (index, value) in array.enumerated() {
            var nextObject = value
            parseDict(&nextObject)
            updatedArray[index] = nextObject
        }
        jsonObject = updatedArray
    }
}

func getValueWith(_ key: String) -> String? {
    return [
        "description" : "Amit (amitpstu1@gmail.com) ... so on"
        ][key]
}
0 голосов
/ 05 августа 2020

Вы можете обновить sh свою память или узнать больше здесь: https://developer.apple.com/documentation/foundation/archives_and_serialization/using_json_with_custom_types Вы бы смотрели на слияние json из раздела с разной глубиной. Использование кодируемого расширения et c.

Вы также можете посмотреть здесь: Можно ли в Swift использовать строку для доступа к свойству структуры? Если вы хотите развернуть свою собственную функцию поиска, как модифицированный dfs или что-то в этом роде.

...