Я создаю общую систему сохранения для Unity. В качестве сериализатора я использую Json.NET.
Основной контейнер данных — это класс, который содержит Dictionary<string/*dataKey*/, ISaveableData/*data to be saved*/>. Поскольку ISaveableData — это интерфейс, я использую конкретный тип в качестве ключа в json. Таким образом я знаю, в какой тип нужно десериализовать данные при загрузке.
Все работает нормально до тех пор, пока я не пытаюсь десериализовать данные в конкретный класс. Я создал собственный конвертер для десериализации, но, похоже, что-то не так.
Мой текущий метод Read() в пользовательском конвертере выглядит примерно так:
public override Data ReadJson(JsonReader reader, Type objectType, Data existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
//load json object
JObject jObject = JObject.Load(reader);
Data data = new();
foreach (JToken token in jObject.Children())
{
//get key
string key = token.Path; //in my example 'key' will either be "DataTypeOne" or "DataTypeTwo"
//determine correct type, based on the key (pseudo-code, this step works fine)
Type type = GetTypeByKey(key);
//now I know the type, I want to deserialize the token into an instance of the specified type
//this fails with error 'Unexpected token while deserializing object: PropertyName. Path 'DataTypeOne'
object deserializedInstance = token.ToObject(type, serializer);
//add to data
data.Add((ISaveable)deserializedInstance);
}
return data;
}
JSON выглядит примерно так:
{
"SaveSlotName": "Example",
"Data": {
"DataTypeOne": {
"SomeValue": 5
},
"DataTypeTwo": {
"SomeOtherValue": "Hello"
}
}
}
Почему JToken.ToObject(type, serializer) выдает ошибку? Как следует использовать метод Read()?





Я нашел проблему.
Я попытался десериализовать токен, но вместо этого мне нужно десериализовать значение токена.
Это новый Read() метод. Возможно, это будет полезно для других, столкнувшихся с той же проблемой.
public override Data ReadJson(JsonReader reader, Type objectType, Data existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
//load json object
JObject jObject = JObject.Load(reader);
Data data = new();
foreach (JToken token in jObject.Properties())
{
//get key
string key = token.Path; //in my example 'key' will either be "DataTypeOne" or "DataTypeTwo"
//determine correct type, based on the key (pseudo-code, this step works fine)
Type type = GetTypeByKey(key);
//get the value of this property
JToken value = property.Value;
//now I know the type and the property value and can deserialize it into an instance of the specified type
object deserializedInstance = value.ToObject(type, serializer);
//add to data
data.Add((ISaveable)deserializedInstance);
}
return data;
}
Вместо JToken.Children() вы можете использовать JObject.Properties(). Если вы это сделаете, вы можете избежать актерского состава.
Какие значения имеют
typeиtoken? Пожалуйста, включите также определение класса дляData.