带有对象属性的只读属性的对象的Newtonsoft json反序列化

时间:2018-10-04 15:48:12

标签: c# .net json.net json-deserialization

大家好,我试图解决以下问题。 我想反序列化Foo类,该类包含Bar对象的列表,而这些对象又包含对Foo对象的引用。 Bar对象中的Foo对象用于检索Num1,从而依次执行一些内部计算(以获取Num3):

public class Foo
{
    [JsonProperty]
    public double Num1 { get; set; }

    [JsonProperty]
    public List<Bar> Bars { get; set; }
}

public class Bar
{
    [JsonProperty]
    public double Num2 { get; set; }

    [JsonProperty]
    public double Num3 => Foo.Num1 * 2;

    private Foo Foo;

    public Bar(Foo foo, double num2)
    {
        Foo = foo;
        Num2 = num2;
    }
}

如果我像下面的示例那样对其进行序列化,则可以正常运行:

        Foo foo = new Foo()
        {
            Num1 = 8,
            Bars = new List<Bar>()
        };

        foo.Bars.Add(new Bar(foo, 3));
        foo.Bars.Add(new Bar(foo, 5));

        string serialised = JsonConvert.SerializeObject(foo);

        // result is {"Num1":8.0,"Bars":[{"Num2":3.0,"Num3":24.0},{"Num2":5.0,"Num3":40.0}]}

但是,如果我尝试反序列化同一字符串:

        Foo deserialised = (Foo)JsonConvert.DeserializeObject(serialised, typeof(Foo));

Foo对象被反序列化,但是Num3属性引发以下空引用错误:

  

(新的System.Collections.Generic.ICollectionDebugView(deserialized.Bars).Items [1])。Num3'引发了类型为'System.NullReferenceException'的异常

这只是一个简单的示例,用于显示我遇到的问题,我认为原因是因为json中的Bar对象没有引用任何Foo对象。实际上,“ Num1”是一个复杂的对象,可以从中检索其他参数,因此无法将Num1存储在Bar类中。

是否有解决此类问题的聪明方法?

编辑:

因此,我发现的临时解决方案是修改上面的代码1),按照Matt Dillard(以及相关的私有字段_Num3)的建议添加设置器,并通过创建用于定义Num3的函数(CalculateNum3)来修改上述代码。在主例程中调用,并更新_Num3的值。这样,Num3由一个函数设置,并且无论何时进行反序列化或序列化,它们都会作用于Num3字段。主要缺点是需要每次调用CalculateNum3函数。

public class Bar
{
    [JsonProperty]
    public double Num2 { get; set; }

    private double _Num3;
    [JsonProperty]
    public double Num3
    {
        get
        {
            return _Num3;
        }
        private set
        {
            _Num3 = value;
        }
    }

    public double CalculateNum3()
    {
        _Num3 = Foo.Num1 * Num2;
        return _Num3;
    }

    private Foo Foo;

    public Bar(Foo foo, double num2)
    {
        Foo = foo;
        Num2 = num2;
    }
}

主要代码

        Foo foo = new Foo()
        {
            Num1 = 8,
            Bars = new List<Bar>()
        };

        Bar bar1 = new Bar(foo, 3);
        bar1.CalculateNum3();
        Bar bar2 = new Bar(foo, 5);
        bar2.CalculateNum3();

        foo.Bars.Add(bar1);
        foo.Bars.Add(bar2);

1 个答案:

答案 0 :(得分:0)

您的问题是Bar.Num3属性尚未设置。从字符串反序列化时,JSON.NET将创建Bar类的全新实例,并将JSON字符串中的值分配给对象。它尝试调用Num3属性的设置器,但没有。