Swift Codable нулевая обработка

У меня есть структура, которая анализирует JSON, используя Codable.

struct Student: Codable {
    let name: String?
    let amount: Double?
    let adress: String?
}

Теперь, если значение суммы равно нулю, синтаксический анализ JSON завершается ошибкой.

Итак, должен ли я вручную обрабатывать нулевые значения для всех Int и Double, присутствующих в структуре Student?

Значения String, поступающие как null, автоматически обрабатываются.


person Ekra    schedule 18.04.2018    source источник
comment
stackoverflow.com/questions/46292325/? Переопределив init(from decoder:). В принятом ответе кажется, что значение Int равно Null.   -  person Larme    schedule 18.04.2018
comment
Значение null (без строки) по умолчанию обрабатывается как nil, поэтому предполагается, что декодирование будет успешным, если свойство является необязательным. Кстати: вы можете опустить CodingKeys.   -  person vadian    schedule 18.04.2018
comment
@vadian - вы имеете в виду, что мне не нужно обрабатывать это отдельно? Как предложили другие   -  person Ekra    schedule 18.04.2018
comment
Если имена свойств совпадают с ключами, вам не нужен явный CodingsKeys. Назовите свойство как (правильно написанное) address и удалите все перечисление.   -  person vadian    schedule 18.04.2018
comment
@vadian - ты сказал - нулевое значение для Int / Double по умолчанию обрабатывается как nil, поэтому предполагается, что декодирование будет успешным, если свойство является необязательным. Таким образом, нет необходимости в дополнительной проводке для обработки случаев. ИЛИ я должен написать decodeIfPresent для всех Int/Double   -  person Ekra    schedule 18.04.2018
comment
Нет необходимости писать собственный инициализатор. Достаточно объявить свойства необязательными (?). Это часть магии Codable. Однако, если значение null представляет собой строку "null", вам нужно написать собственный инициализатор, а затем, пожалуйста, обвините владельца службы в отправке этого ужасного JSON.   -  person vadian    schedule 18.04.2018
comment
Я не могу воспроизвести это. Можете ли вы показать JSON, который не декодируется для вас? Добавление "amount": null в мой JSON работает нормально.   -  person Rob Napier    schedule 18.04.2018


Ответы (2)


Позвольте мне сделать для вас эту игровую площадку, так как пример показывает вам более сотни слов:

import Cocoa

struct Student: Codable {
    let name: String?
    let amount: Double?
    let adress: String?
}

let okData = """
{
   "name": "here",
 "amount": 100.0,
 "adress": "woodpecker avenue 1"
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let okStudent = try decoder.decode(Student.self, from:okData)
print(okStudent)

let nullData = """
{
   "name": "there",
 "amount": null,
"adress": "grassland 2"
}
""".data(using: .utf8)!

let nullStudent = try decoder.decode(Student.self, from:nullData)
print(nullStudent)

null прекрасно обрабатывается, если вы определяете свои структуры с помощью опций. Однако я бы посоветовал против этого, если вы можете избежать этого. Swift обеспечивает наилучшую поддержку, которую я знаю, чтобы помочь мне не забыть обработать nil случаев, где бы они ни возникали, но они по-прежнему являются занозой в заднице.

person Patru    schedule 18.04.2018
comment
когда я пытаюсь закодировать нулевое целое число и отправить его в свой веб-API, int выходит из строя из json, и мне нужно отправить нулевое целое число на сервер, как это исправить? - person Ben Shabat; 09.01.2019
comment
@BenShabat Вы должны опубликовать свой код в виде вопроса и показать JSON, который вы хотите отправить. Я не уверен, что JSONEncoder будет отправлять поля с нулевым значением, но вы должны предоставить больше контекста, чем вы можете опубликовать в комментарии. Вы можете опубликовать ссылку на свой вопрос в качестве комментария, если хотите. - person Patru; 11.01.2019

Просматривал Codable и получил эту проблему.

Итак, чтобы быть очень ясным, вот что: если JSON/ответ будет содержать null в качестве значения, он интерпретируется как nil. И, следовательно, по этой причине одно из свойств модели, которое может содержать null, должно быть помечено как необязательное.

Например, рассмотрим приведенный ниже ответ JSON:

{
"name": "Steve",
"amount": null,
"address": "India"
}

Модель должна быть такой, как показано ниже, потому что amount возвращает null.

struct Student: Codable {
    let name: String
    let amount: Double?
    let address: String
}

Suggestion: В случае, если вы хотите написать init(from decoder: Decoder) throws, всегда используйте что-то вроде приведенного ниже для необязательных свойств.

init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        amount = try values.decodeIfPresent(String.self, forKey: .amount)
        //so on...
    }

Даже если вы добавите блок do-catch с try? decoder...., он может быть захвачен в случае сбоя. Надеюсь понятно!! Это просто, но очень сложно найти проблему, даже если модель содержит 5 или более свойств, некоторые из которых содержат null значений.

person Vinayak GH    schedule 21.01.2019
comment
вы сделали адрес необязательным. количество должно быть необязательным. - person Somoy Das Gupta; 01.02.2019
comment
@VinayakGH Знание о decodeIfPresent помогло мне сегодня. - person mharper; 19.03.2019
comment
Я получаю нулевое значение, например ‹null›, как мне проверить такой ответ в декодере? - person Hari Narayanan; 24.12.2019
comment
@HariNarayananВам нужно скрыть JSON для данных с использованием utf8, прежде чем выполнять декодирование. Например, пусть данные = json.data (используя: String.Encoding.utf8). Он преобразует ‹null› в null. Теперь вы используете эти данные для декодирования. Я надеюсь, что это помогает. - person Gurjinder Singh; 02.01.2020