简体   繁体   English

Newtonsoft.json:如果反序列化错误,请尝试不同的 class

[英]Newtonsoft.json: If deserialization error, try different class

I have a class myClass which I have recently refactored.我有一个最近重构的 class myClass Originally, it contained properties string Category and string Value , and serialized as最初,它包含属性string Categorystring Value ,并序列化为

{
   "Category": "someCategory",
   "Value": "someValue"
}

After refactoring, it now contains properties Signature Sig and ExtraData Data , where Signature is a class containing the original properties string Category and string Value , so it deserializes as重构后,它现在包含属性Signature SigExtraData Data ,其中Signature是一个 class 包含原始属性string Categorystring Value ,因此它反序列化为

{
   "Sig":{
      "Category": "someCategory",
      "Value": "someValue"
   },
   "ExtraData": { ... large set of additional data here}
}

myClass is a shared class used extensively throughout my program, usually in the context of List<myClass> , and is serialized as part of saving several different types of larger overarching settings classes. myClass是一个共享的 class 在我的程序中广泛使用,通常在List<myClass>的上下文中,并且作为保存几种不同类型的较大总体设置类的一部分进行序列化。 When I try to deserialize these settings files using the updated class definition, the deserializer (of course) fails to deserialize the existing string, resulting in empty lists that had previously been populated.当我尝试使用更新的 class 定义反序列化这些设置文件时,反序列化器(当然)无法反序列化现有字符串,从而导致先前填充的空列表。

I am wondering if it's possible to implement the following logic using a JsonConverter or ContractResolver (pseudocode)我想知道是否可以使用JsonConverterContractResolver (伪代码)实现以下逻辑

///jsonString here should be the fragment of the larger json file containing just the current object

myclass attempt = JsonConvert.DeserializeObject<myClass>(jsonString);

if (attempt == null) // or whichever method is best to determine deserialization success
{
   Signature attempt2 = JsonConvert.DeserializeObject<Signature>(jsonString);
   if (attempt2 != null)
   { 
      myClass converted = new();
      converted.Sig = attempt2;
      return converted;
   }
   else
   {
      return null; // or whatever behavior is used to skip populating the list
   }
}
else
{
   return attempt; // from a settings file which had already been upgraded
}

I tried implementing a JsonConverter but got stuck on the ReadJson() function at object value = reader.Value;我尝试实现一个JsonConverter ,但在 object 处卡住了ReadJson() object value = reader.Value; - it seemed like value was only generated one line at a time (eg in my case as "Category": "someCategory" ) instead of the entire object, so I couldn't deserialize it to a Signature class as it only contained half of the required data. - 似乎value一次只生成一行(例如,在我的情况下为"Category": "someCategory" )而不是整个 object,所以我无法将其反序列化为Signature class,因为它只包含一半所需的数据。

Is there a way to implement the desired behavior?有没有办法实现所需的行为?

I usually use a JsonConstructor in this case, it will properly deserialize both of your jsons.在这种情况下,我通常使用 JsonConstructor,它会正确反序列化你的两个 json。

    MyClass myClass = JsonConvert.DeserializeObject<MyClass>(json);

public class MyClass
{
    public Sig Sig { get; set; }
    public ExtraData ExtraData { get; set; }
    
    [JsonConstructor]
    public MyClass(Sig Sig, string Category, string Value)
    {
        if (Sig != null) this.Sig = Sig;
        else
        {
            this.Sig = new Sig
            {
                Category = Category,
                Value = Value
            };
        }
    }
    public MyClass() {}
}

public class Sig
{
    public string Category { get; set; }
    public string Value { get; set; }
}
public class ExtraData
{
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM