*** Обновлено: уточнено, что есть два отдельных файла JSON ***
У меня есть два класса:
public class Phone
{
public int PhoneId { get; set; }
public string Name { get; set; }
public Manufacturer PhoneManufacturer { get; set; }
}
public class Manufacturer
{
public int ManId { get; set; }
public string Name { get; set; }
}
И два файла JSON, содержащие данные для обоих классов:
Телефоны.json:
[
{
"phoneId" : 45,
"name": "S20",
"phoneManufacturer":16
}
]
Производители.json:
[
{
"manId" : 16,
"name": "Samsung"
}
]
Я использую следующий код для десериализации объектов телефонов:
string jsonString = File.ReadAllText("phones.json");
return JsonSerializer.Deserialize<List<Phone>>(jsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true})!;
Я хочу, чтобы при десериализации JSON телефонов в List<Phone> свойство PhoneManufacturer результирующих объектов было заполнено фактическим объектом Manufacturer.
При запуске десериализации с параметрами по умолчанию я получаю ошибку, что JSON не может преобразовать значение в свойстве PhoneManufacturer в объект Manufacturer, что имеет смысл, поскольку это идентификатор объекта, а не сам объект.
Как я могу этого добиться?
Как выглядит jsonString? Можете ли вы изменить данные JSON, чтобы они соответствовали структуре класса C Sharp?
Ваш JSON выглядит как неправильный/хороший формат
Я отредактировал вопрос, чтобы внести ясность. Есть два файла JSON, а переменная jsonString хранит содержимое файла phone.json.
Вам нужно написать собственный преобразователь для ручного сопоставления идентификаторов с объектами. Существует отличная серия статей, посвященных этой теме как для NewtonSoft, так и для System.Text.Json: Работа с сериями JSON. Раздел, помеченный Multi-Value Type Collections, похож на то, что вы пытаетесь сделать.
Если вы используете System.Text.Json и не возражаете против изменения класса для добавления нового конструктора, это вполне достижимо, если у вас есть коллекция производителей, доступных для конструктора Phone. Что-то вроде:
[JsonConstructor]
public Phone(int phoneId, string name, int phoneManufacturer)
{
PhoneId = phoneId;
Name = name;
if (!ManufacturerDictionary.Contains(phoneManufacture)) throw new Exception();
PhoneManufacturer = ManufacturerDictionary.[phoneManufacturer];
}
О, и сначала загрузите Manufacturers.json 😉
Вы можете попробовать этот код
var phonesJsonArr = JsonNode.Parse(phonesJson).AsArray();
var manufacturersJsonArr = JsonNode.Parse(manufacturersJson).AsArray();
foreach (JsonNode node in phonesJsonArr)
{
var manId = node["phoneManufacturer"].GetValue<int>();
node["PhoneManufacturer"] = new JsonObject
{
["manId"] = manId,
["Name"] = manufacturersJsonArr.Where(ja => ja["manId"].GetValue<int>() == manId).Select(ja => ja["name"].GetValue<string>()).FirstOrDefault()
};
node.AsObject().Remove("phoneManufacturer");
}
List<Phone> phones = phonesJsonArr.Deserialize<List<Phone>>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true});
У результирующих объектов свойство PhoneManufacturer будет заполнено фактическим объектом Manufacturer. Я не думаю, что у вас есть правильный файл json.