C# Newtonsoft反序列化在反序列化其他列表中的列表时重复元素
我有一个对象列表(a),每个对象包含一个对象列表(B)。我对As列表进行了序列化,没有问题,但是 当我对As进行反序列化时,每个A中的B列表中的B数量是原来的两倍。为什么会这样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
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