Как десериализовать текст JSON в список объектов в C #, используя JsonConvert.DeserializeObject - PullRequest
0 голосов
/ 12 ноября 2010

У меня есть данные JSON, как показано ниже. Я включил имена столбцов только один раз, чтобы сохранить размер данных. Пожалуйста, дайте мне знать, как мне преобразовать это в список объектов C #.

// JSON
{
    "COLUMNS": [
        "id", "country","lastname", "firstname", "email", "category"
    ], 
    "DATA": [
        [43, "USA", "jon", "doe", "doe@gmail.com", "HR"], 
        [44, "JAPAN", "tanaka", "yidi", "yidi@aol.com", "IT"]
    ]
}

// .NET
Employee emp = JsonConvert.DeserializeObject<Employee>(jsonData);  

Я должен иметь доступ к свойствам объекта, например emp.lastname.

Кроме того, как видно из заголовка, я использую класс JsonConvert в библиотеке Json.NET .

1 Ответ

1 голос
/ 12 ноября 2010

Вы не сможете использовать класс JsonConvert напрямую, так как он ожидает, что все свойства будут иметь имя / отображение, и не сможет установить его, потому что вы по сути используете пользовательский формат.

Что вам нужно сделать, это создать класс, содержащий столбцы и данные, и сериализовать в него, например, так:

class CustomData
{
    public string Columns { get; set; }
    public object[,] Data { get; set; }
}

JsonConvert должен иметь возможность конвертировать ваши данные в эту структуру в .NET.

Оттуда это становится проблемой .NET, так как вам нужно получить имена столбцов и данных. Вы должны быть в состоянии использовать LINQ, чтобы помочь в сопряжении двух, а затем использовать отражение для заполнения вашего элемента:

// The custom data structure, deserialized from JSON.
CustomData data = ...;

// The type of Employee.
Type type = typeof(Employee);

// Create a map of the property info to the ordinal in the
// Columns.
IDictionary<int, PropertyInfo> propertyMap = data.Columns.
    Select((p, i) => 
        new { Index = i, PropertyInfo = type.GetProperty(p) }).
    ToDictionary(p => p.Index, p => p.PropertyInfo);

// Cycle through the rows in the data.
var query =
    // Cycle through all of the rows.
    from row in Enumerable.Range(0, data.Data.GetLength(0))

    // Create the instance.
    let instance = new Employee()

    // For each column in the row.
    from column in Enumerable.Range(0, data.Data.GetLength(1))

    // Lookup the property info.
    let propertyInfo = propertyMap[column]

    // Select the instance, the property, and the value.
    select { 
        // This is used for grouping purposes, since
        // you can't guarantee that the type you are serializing
        // to will have natural identity properties and
        // you know the row corresponds to one singular instance.
        Row = row,
        Instance = instance, 
        PropertyInfo = propertyInfo,
        Value = data.Data[row, column]
    };

// Iterate through the items, setting the instance values.
foreach (var propertyAndData in query)
{
    // Set the property value on the instance.
    propertyAndData.PropertyInfo.
        SetValue(propertyAndData.Instance, Value, null);
}

// Group by the row and get the first item in each sequence.
IEnumerable<Employee> employees =
    from item in query
    groupby item by item.Row into g
    select g.First();

Единственное предостережение для вышеперечисленного; если вы используете тип значения, то вы не заполняете тот же экземпляр, что итерируете это. Для обработки типов значений необходимо развернуть запрос LINQ и выполнить итерацию по каждой строке и столбцу, используя циклы for, создавая новый экземпляр в каждой новой строке, а затем используя Reflection, как указано выше, для заполнения свойств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...