C# Newtonsoft反序列化在反序列化其他列表中的列表时重复元素

C# Newtonsoft反序列化在反序列化其他列表中的列表时重复元素,c#,json.net,deserialization,C#,Json.net,Deserialization,我有一个对象列表(a),每个对象包含一个对象列表(B)。我对As列表进行了序列化,没有问题,但是 当我对As进行反序列化时,每个A中的B列表中的B数量是原来的两倍。为什么会这样 var sample = new List<A> { new A { Flag = true, Amount = 10, Bs = n

我有一个对象列表(a),每个对象包含一个对象列表(B)。我对As列表进行了序列化,没有问题,但是 当我对As进行反序列化时,每个A中的B列表中的B数量是原来的两倍。为什么会这样

        var sample = new List<A>
        {
            new A
            {
                Flag = true,
                Amount = 10,
                Bs = new List<B>
                {
                    new B {Amount = 4, Id = Guid.NewGuid()},
                    new B {Amount = 6, Id = Guid.NewGuid()}
                }
            },
            new A
            {
                Flag = true,
                Amount = 20,
                Bs = new List<B>
                {
                    new B {Amount = 4, Id = Guid.NewGuid()},
                    new B {Amount = 6, Id = Guid.NewGuid()}
                }
            },
            new A
            {
                Flag = false,
                Amount = 30,
                Bs = new List<B>
                {
                    new B {Amount = 4, Id = Guid.NewGuid()},
                    new B {Amount = 6, Id = Guid.NewGuid()}
                }
            }
        };

        var serialized = JsonConvert.SerializeObject(sample, ContractResolver.AllMembersSettings);
        var deserialized = JsonConvert.DeserializeObject<List<A>>(serialized, ContractResolver.AllMembersSettings);
var样本=新列表
{
新的
{
Flag=true,
金额=10,
Bs=新列表
{
新的B{Amount=4,Id=Guid.NewGuid()},
新B{Amount=6,Id=Guid.NewGuid()}
}
},
新的
{
Flag=true,
金额=20,
Bs=新列表
{
新的B{Amount=4,Id=Guid.NewGuid()},
新B{Amount=6,Id=Guid.NewGuid()}
}
},
新的
{
Flag=false,
金额=30,
Bs=新列表
{
新的B{Amount=4,Id=Guid.NewGuid()},
新B{Amount=6,Id=Guid.NewGuid()}
}
}
};
var serialized=JsonConvert.serialized对象(示例,ContractResolver.AllMembersSettings);
var deserialized=JsonConvert.DeserializeObject(序列化,ContractResolver.AllMembersSettings);

A类
{
公共布尔标志{get;set;}
公共十进制数{get;set;}
公共列表Bs{get;set;}
}
B类
{
公共Guid Id{get;set;}
公共十进制数{get;set;}
}
公共类ContractResolver:DefaultContractResolver
{
公共静态只读JsonSerializerSettings所有成员设置=
新JsonSerializerSettings
{
TypeNameHandling=TypeNameHandling.All,
ContractResolver=新的ContractResolver()
};
受保护的重写IList CreateProperties(类型类型,MemberSerialization MemberSerialization)
{
var道具=
类型
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(p=>p.CanRead和p.CanWrite)
.Select(p=>base.CreateProperty(p,memberSerialization))
.工会(
类型
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f=>base.CreateProperty(f,memberSerialization)))
.ToList();
ForEach(p=>{p.writeable=true;p.Readable=true;});
返回道具;
}
}

正如我在问题中提到的,我不确定为什么您有ContractResolver,但当我使用以下工具时:

string sampleData = Newtonsoft.Json.JsonConvert.SerializeObject(sample);
List<A> test = Newtonsoft.Json.JsonConvert.DeserializeObject<List<A>>(sampleData);
string sampleData=Newtonsoft.Json.JsonConvert.SerializeObject(示例);
List test=Newtonsoft.Json.JsonConvert.DeserializeObject(sampleData);
数据按预期进行序列化和反序列化。

之所以发生这种情况,是因为C#编译器在后台为属性生成了一个备份字段

您可以删除自定义的解析器,让Json.NET发挥它的魔力,或者在最后使用小技巧

自动实现(自动实现)属性自动执行此操作 图案更具体地说,非抽象属性声明是 允许有分号访问器主体。两个访问器都必须是 present和两者都必须有分号体,但它们可以有 不同的可访问性修饰符。当属性被指定为 这样,将自动为 属性,访问器将被实现为读写 到那个后场去。支持字段的名称是compiler 已生成,用户无法访问

你可以通过使用一个小技巧来实现你想要的,尽管我建议你不要这样做。
此外,如果您确实需要
BindingFlags.NonPublic
,我会重新考虑,因为单独删除它可以解决您的问题

小黑客

type
    .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
    .Where(field => !field.Name.EndsWith("k__BackingField"))
    .Select(f => base.CreateProperty(f, memberSerialization))
)

我通过将
ObjectCreationHandling
设置为
Replace

来自Newtonsoft文档:

型号:

public class UserViewModel
{
    public string Name { get; set; }
    public IList<string> Offices { get; private set; }

    public UserViewModel()
    {
        Offices = new List<string>
        {
            "Auckland",
            "Wellington",
            "Christchurch"
        };
    }
}
public类UserViewModel
{
公共字符串名称{get;set;}
公共IList办公室{get;private set;}
公共用户视图模型()
{
办公室=新名单
{
“奥克兰”,
“惠灵顿”,
“基督城”
};
}
}
示例代码:

string json = @"{
  'Name': 'James',
  'Offices': [
    'Auckland',
    'Wellington',
    'Christchurch'
  ]
}";

UserViewModel model1 = JsonConvert.DeserializeObject<UserViewModel>(json);

foreach (string office in model1.Offices)
{
    Console.WriteLine(office);
}
// Auckland
// Wellington
// Christchurch
// Auckland
// Wellington
// Christchurch

UserViewModel model2 = JsonConvert.DeserializeObject<UserViewModel>(json, new JsonSerializerSettings
{
    ObjectCreationHandling = ObjectCreationHandling.Replace
});

foreach (string office in model2.Offices)
{
    Console.WriteLine(office);
}

// Auckland
// Wellington
// Christchurch
stringjson=@”{
'姓名':'詹姆斯',
“办公室”:[
“奥克兰”,
“惠灵顿”,
“基督城”
]
}";
UserViewModel model1=JsonConvert.DeserializeObject(json);
foreach(model1.office中的字符串办公室)
{
控制台、书写线(办公室);
}
//奥克兰
//惠灵顿
//基督城
//奥克兰
//惠灵顿
//基督城
UserViewModel model2=JsonConvert.DeserializeObject(json,新的JsonSerializerSettings
{
ObjectCreationHandling=ObjectCreationHandling.Replace
});
foreach(model2.office中的字符串办公室)
{
控制台、书写线(办公室);
}
//奥克兰
//惠灵顿
//基督城

我真的不明白为什么会使用默认设置复制它们,或者为什么你会想要这样,但是他们的例子正是发生在我身上的事情。

可能是C#编译器在后台添加了属性作为后台字段。我对NewtonSoft不太熟悉,但是我用它来序列化/反序列化类,但是为什么你有一个ContractResolver类?我用ContractResolver类来避免在我的类上放置属性作为一个有趣的问题,你为什么要这样做?我刚刚将解析器添加到我的项目中,以查看它实际做了什么,这使得序列化数据比它需要的复杂得多(也更大),但这肯定是有原因的
string json = @"{
  'Name': 'James',
  'Offices': [
    'Auckland',
    'Wellington',
    'Christchurch'
  ]
}";

UserViewModel model1 = JsonConvert.DeserializeObject<UserViewModel>(json);

foreach (string office in model1.Offices)
{
    Console.WriteLine(office);
}
// Auckland
// Wellington
// Christchurch
// Auckland
// Wellington
// Christchurch

UserViewModel model2 = JsonConvert.DeserializeObject<UserViewModel>(json, new JsonSerializerSettings
{
    ObjectCreationHandling = ObjectCreationHandling.Replace
});

foreach (string office in model2.Offices)
{
    Console.WriteLine(office);
}

// Auckland
// Wellington
// Christchurch