Swift 5 Разбор странного формата json

Я пытаюсь разобрать JSON, но продолжаю получать ошибку неправильного формата. JSON, который я получаю от FoodData Central (API питания Министерства сельского хозяйства США), выглядит следующим образом:

{
    dataType = "Survey (FNDDS)";
    description = "Chicken thigh, NS as to cooking method, skin not eaten";
    fdcId = 782172;
    foodNutrients =     (
                {
            amount = "24.09";
            id = 9141826;
            nutrient =             {
                id = 1003;
                name = Protein;
                number = 203;
                rank = 600;
                unitName = g;
            };
            type = FoodNutrient;
        },
                {
            amount = "10.74";
            id = "9141827";
            nutrient =             {
                id = 1004;
                name = "Total lipid (fat)";
                number = 204;
                rank = 800;
                unitName = g;
            };
            type = FoodNutrient;
        }
    );
}

Мои структуры:

struct Root: Decodable {
     let description: String
     let foodNutrients: FoodNutrients
}

struct FoodNutrients: Decodable {
     // What should go here???
}

Из JSON видно, что foodNutrients представляет собой массив безымянных объектов, каждый из которых имеет значения суммы: String, id: String и питательное вещество: Nutrient (у которого есть id, имя и т. д.). Однако, забывая объект Nutrient , я даже не могу разобрать суммы.

struct FoodNutrients: Decodable {
     let amounts: [String]
}

Я не думаю, что это массив строк, но я понятия не имею, что будет указывать () в foodNutrients.

Как мне разобрать этот JSON. Я использую Swift 5 и JSONDecoder. Чтобы получить JSON, я использую JSONSerializer, а затем распечатываю JSON выше.


person Nobadi    schedule 26.07.2020    source источник
comment
Это не очень хорошо отформатированный json. Я проверил форматировщик и валидатор json. НЕДЕЙСТВИТЕЛЬНО (RFC 8259)   -  person Danizavtz    schedule 27.07.2020
comment
Я также проверил это, что странно, потому что это исходит от API Министерства сельского хозяйства США. Все, что я делаю, чтобы получить этот ответ, — это использование JSONSerialization для преобразования данных в JSON, а затем их печать.   -  person Nobadi    schedule 27.07.2020


Ответы (2)


() в foodNutrients указывает, что он содержит массив объектов — в этом случае объектов FoodNutrient. Поэтому ваш корневой объект должен выглядеть так:

struct Root: Decodable {
    let description: String
    let foodNutrients: [FoodNutrient]
}

Теперь foodNutrient, за исключением объекта питательных веществ, прост:

struct FoodNutrient: Decodable {
    let id: Int // <-- in your example it is an integer and in the second object a string, choose the fitting one from the API
    let amount: String
    let nutrient: Nutrient
}

И питательный объект должен выглядеть так:

struct Nutrient: Decodable {
    let name: String
    let number: Int
    let rank: Int
    let unitName: String 
}

Использование Decodable — это хороший и простой способ сериализации JSON. Надеюсь, это поможет. Удачного кодирования :)

person mflknr    schedule 26.07.2020
comment
Я получаю ту же ошибку: данные не могут быть прочитаны, потому что они не в правильном формате. - person Nobadi; 27.07.2020
comment
Это решение правильное. Единственная проблема заключается в том, что переменная суммы регистрируется как Double, а не как String. - person Nobadi; 27.07.2020

Это не JSON. Это список свойств в формате openStep.

Вот как это можно смоделировать (используйте String вместо Int):

struct Root: Decodable {
    let description: String
    let foodNutrients: [FoodNutrient]
}

struct FoodNutrient: Decodable {
    let id: String
    let amount: String
    let nutrient: Nutrient
}

struct Nutrient: Decodable {
    let name: String
    let number: String
    let rank: String
    let unitName: String
}

А затем расшифровать это так:

try PropertyListDecoder().decode(Root.self, from: yourStr)
person pawello2222    schedule 26.07.2020
comment
Я получаю эту ошибку: данные не могут быть прочитаны, потому что они не в правильном формате. - person Nobadi; 27.07.2020
comment
@Nobadi Вы пытаетесь расшифровать точные данные, которые вы разместили? И не печатать error.localizedDescription - бессмысленно. Вместо этого укажите ошибку как DecodingError. - person pawello2222; 27.07.2020
comment
отрицательный. Я показываю только часть, так как весь ответ от RESTApi огромен. Однако я вставил весь ответ в документы Google: docs.google. ком/документ/d/ - person Nobadi; 27.07.2020
comment
и что мне делать после приведения его к DecodingError? - person Nobadi; 27.07.2020
comment
@Nobadi Распечатай. Отлаживать. Проверьте, какой это тип DecodingError. Я показал вам, как расшифровать пример из вашего вопроса. Теперь вы должны быть в состоянии сделать все остальное. - person pawello2222; 27.07.2020
comment
Большое спасибо, я понял это после того, как напечатал ошибку, а не локализованное описание. После отладки я обнаружил, что JSON на самом деле в порядке, но переменная суммы не является строкой, а является двойной (что странно, потому что она завернута в , но да ладно). Я ценю быстрые и прямые ответы. - person Nobadi; 27.07.2020