如何在自定义 Json.NET 转换器中反序列化令牌

问题描述 投票:0回答:1

我正在为 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()
方法应该如何使用?

c# json json.net converters
1个回答
0
投票

我发现了问题。

我尝试反序列化令牌,但我需要反序列化令牌的值。

这是新的

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())
        {
            //cast token to property
            var property = (JProperty)token;

            //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;
    }
© www.soinside.com 2019 - 2024. All rights reserved.