WebAPI 2 JSON 序列化带有嵌套静态对象实例的对象数组失败

WebAPI 2 JSON serialization of object-arrays with nested static object instances fails

我需要一个 Web API 服务,其中包含一些用于新 PoC 的虚假数据。这个对象模型非常简单,2 类,其中 class1 有一个 class2 的嵌套数组。 所以我开始构建一个 FakeDataService,我只是硬编码了一些数据。 为了简洁起见,我在这个示例中省略了很多属性,所以代码集中在问题的本质上:

public class Class1
{
    public string Prop1 { get; set; }
    public IEnumerable<Class2> Prop2 { get; set; }
    public IEnumerable<string> Prop3 { get; set; }
}    

public class Class2
{
    public string Prop4 { get; set; }
}

public static class FakeDatabase
{
    public static Class1 c1instance1 = new Class1 { Prop1 = "value1", 
                          Prop2 = new Class2[] { c2instance1 }, 
                          Prop3 = new string[] { "value3" } };

    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" };

    public static Class1[] AllData = new Class1[] { c1instance1 };

}

所以,我的假数据库的 "AllData" 是一个 Class1 对象的数组("array" 在这个例子中只有一个),并且 Class1 对象有一个字符串 属性 (prop1 ),一组 Class2 对象 (prop2),和一组字符串 属性 (prop3),而 Class2 对象只有一个字符串 属性 (prop4).

WebAPI 控制器非常基础:

public class ValuesController : ApiController
{

    // GET api/values
    public IEnumerable<Class1> Get()
    {
        return FakeDatabase.AllData;                                                                                                                                                                                       
    }

但是当我调用值控制器时,结果是:

<ArrayOfClass1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FakeDataService.Models">
<Class1>
<Prop1>value1</Prop1>
<Prop2>
<Class2 i:nil="true"/>
</Prop2>
<Prop3 xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d3p1:string>value3</d3p1:string>
</Prop3>
</Class1>
</ArrayOfClass1>

注意 Class2 对象的序列化如何产生 i:nil=true

经过几个小时的搜索(我的示例数据比这里的这个简单示例大很多),我发现问题的根源在于嵌套对象数组被定义为静态实例。例如。将 FakeDatabase 的初始代码更改为:

public static class FakeDatabase
    {
        public static Class1 c1instance1 = new Class1 { Prop1 = "value1", 
                Prop2 = new Class2[] { new Class2 { Prop4 = "Value4" }},
                Prop3 = new string[] { "value3" } };


        public static Class1[] AllData = new Class1[] { c1instance1 };

}

调用 WebAPI 控制器现在给我(正确):

<ArrayOfClass1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FakeDataService.Models">
<Class1>
<Prop1>value1</Prop1>
<Prop2>
<Class2>
<Prop4>Value4</Prop4>
</Class2>
</Prop2>
<Prop3 xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d3p1:string>value3</d3p1:string>
</Prop3>
</Class1>
</ArrayOfClass1>

所以唯一的区别是 Class2 对象的数组。这种行为的解释是什么?

您的问题是您在初始化之前使用了 c2instance1 静态变量。来自 C# Language Specification §10.4.5.1 Static field initialization:

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration.

因此,在您的 FateDatabase class 中,c1instance1c1instance1 的初始值设定项使用,同时它仍然为空:

public static class FakeDatabase
{
    public static Class1 c1instance1 = new Class1
    {
        Prop1 = "value1",
        Prop2 = new Class2[] { c2instance1 }, // NOT INITIALIZED YET, THUS NULL
        Prop3 = new string[] { "value3" }
    };

    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" };

    public static Class1[] AllData = new Class1[] { c1instance1 };
}

翻转静态变量的文本顺序以修复错误:

public static class FakeDatabase
{
    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" };

    public static Class1 c1instance1 = new Class1
    {
        Prop1 = "value1",
        Prop2 = new Class2[] { c2instance1 },
        Prop3 = new string[] { "value3" }
    };

    public static Class1[] AllData = new Class1[] { c1instance1 };
}