C# JSON将不同的命名对象反序列化到集合c中#
我必须将给定的JSON字符串读入C#对象。到目前为止还不错,但这个案子对我来说有点特别。JSON字符串包含2个实体。一个是平面对象,第二个是列表,至少在JSON中是逻辑的,但实际上不是。我希望你能帮我找到解决办法 为了更好地解释,我将向您展示我的JSON输入的一部分:C# JSON将不同的命名对象反序列化到集合c中#,c#,json,collections,deserialization,C#,Json,Collections,Deserialization,我必须将给定的JSON字符串读入C#对象。到目前为止还不错,但这个案子对我来说有点特别。JSON字符串包含2个实体。一个是平面对象,第二个是列表,至少在JSON中是逻辑的,但实际上不是。我希望你能帮我找到解决办法 为了更好地解释,我将向您展示我的JSON输入的一部分: { "game":{"GameMode":"1","IsNetworkMode":"1","NbMaxPlayer":"12","GameState":"1"}, "player_56":{"PlayerUserId":"137
{
"game":{"GameMode":"1","IsNetworkMode":"1","NbMaxPlayer":"12","GameState":"1"},
"player_56":{"PlayerUserId":"137187","PlayerIALevel":"-1","PlayerObserver":"0"},
"player_7":{"PlayerUserId":"3440","PlayerIALevel":"-1","PlayerObserver":"0"}
}
我想将播放器实体序列化为这种类型的对象集合。问题是它们并没有真正存储为JSON中的集合。它们的动态名称为“player_56”,数字的逻辑顺序与“1,2,3”不同
目前,我正在使用DataContractJsonSerializer
执行此任务
[DataContract]
public class AlbReplay
{
[DataMember(Name = "game")]
public AlbGame Game { get; set; }
[DataMember(Name = "player")]
public List<AlbPlayer> Players { get; set; }
}
[DataContract]
公演
{
[DataMember(Name=“game”)]
公共AlbGame游戏{get;set;}
[DataMember(Name=“player”)]
公共列表玩家{get;set;}
}
有什么建议吗?将JSON压缩到播放器对象的集合中
player_8: {...}
player_99: {...}
到
如何处理JSON,正则表达式可能就足够了
编辑以下是使用正则表达式破坏字符串的代码。我们做了一些假设:游戏和玩家对象中没有嵌入对象,玩家对象列表是json字符串的最后一部分
string json_test = @"{
""game"":{""GameMode"":""1"",""IsNetworkMode"":""1"",""NbMaxPlayer"":""12"",""GameState"":""1""},
""player_56"" : {""PlayerUserId"":""137187"",""PlayerIALevel"":""-1"",""PlayerObserver"":""0""},
""player_2"": {""PlayerUserId"":""137187"",""PlayerIALevel"":""-1"",""PlayerObserver"":""0""}
}";
json_test = new Regex(@"""player_(\d+)""\s*:\s*{").Replace(json_test, @"""player"" : {""Id"": $1,");
Console.WriteLine("player_##:{...} -> player:{id: ##,..}");
Console.WriteLine(json_test);
json_test = new Regex(@"""player""\s*:\s*{").Replace(json_test, @"""players"" : [{", 1);
json_test = new Regex(@"""player""\s*:\s*{").Replace(json_test, @"{");
json_test = new Regex(@"}$").Replace(json_test, @"]}");
Console.WriteLine("player:{...}, -> players: [{...},...]");
Console.WriteLine(json_test);
与所有关于速度的考虑一样,您必须对其进行测试,如果我必须优化上述内容,将Regex对象作为静态和可重用对象将是我的第一步。我不知道
DataContractJsonSerializer
的范围,但是,您可以在类上实现一个接口来定义如何解析JSON
但如果您能够使用:
然后可以使用Linq转换为JSON:
var data = @"{
""game"":{""GameMode"":""1"",""IsNetworkMode"":""1"",""NbMaxPlayer"":""12"",""GameState"":""1""},
""player_56"":{""PlayerUserId"":""137187"",""PlayerIALevel"":""-1"",""PlayerObserver"":""0""},
""player_7"":{""PlayerUserId"":""3440"",""PlayerIALevel"":""-1"",""PlayerObserver"":""0""}
}";
JObject o = JObject.Parse(data);
IEnumerable<Player> players =
o.Children()
.Where(p => ((JProperty)p).Name.StartsWith("player"))
.Select(p =>
new Player
{
Id = int.Parse(((JProperty)p).Name.Split('_')[1]),
PlayerUserId = int.Parse((string)p.Children<JObject>().First()["PlayerUserId"]),
PlayerIALevel = int.Parse((string)p.Children<JObject>().First()["PlayerIALevel"]),
PlayerObserver = int.Parse((string)p.Children<JObject>().First()["PlayerObserver"]),
});
var data=@”{
“游戏”“:{”“游戏模式”“:”“1”“IsNetworkMode”“:”“1”“NbMaxPlayer”“:”“12”“游戏状态”“:”“1”“},
“player_56”“:{”“PlayerUserId”“:”“137187”“playerLevel”“:”“-1”“PlayerObserver”“:”“0”“,
“player_7”“:{”“PlayerUserId”“:”“3440”“playerLevel”“:”“-1”“PlayerObserver”“:”“0”“}
}";
JObject o=JObject.Parse(数据);
数不清的玩家=
o、 儿童()
.Where(p=>((JProperty)p).Name.StartsWith(“玩家”))
.选择(p=>
新玩家
{
Id=int.Parse(((JProperty)p).Name.Split(“”“)[1]),
PlayerUserId=int.Parse((字符串)p.Children().First()[“PlayerUserId]”),
PlayerIALevel=int.Parse((字符串)p.Children().First()[“PlayerIALevel”]),
PlayerObserver=int.Parse((字符串)p.Children().First()[“PlayerObserver”]),
});
到目前为止我已经试过了:[DataContract]公共类AlbReplay{[DataMember(Name=“game”)]公共AlbGame{get;set;}[DataMember(Name=“player”)]公共列表玩家{get;set;}您可以控制这个JSON吗?理想情况下,你需要一系列的玩家。动态属性不是很有用!您可以序列化为动态对象,只查找以“player”开头的属性,但这不是很好。不,很遗憾,不是。如果没有其他选择,我必须去做这样的事情,谢谢你到目前为止!谢谢你的回答!如果没有其他方法,我必须在反序列化之前进行一些字符串操作。奇怪的是,我必须用相当多的文件来做这件事。我担心我的表现:)@John Smuf-使用这种JSON总是一个问题,它需要在某个时候进行转换。我在我的回答中添加了针对您具体情况的正则表达式替换。您可以尝试的另一件事是.NET的动态对象,然后您可以将所有对象强制转换为字典,并使用以player开头的键将所有对象强制转换为player类,但不确定它是否有效,甚至更快。
public class Player
{
public int Id { get; set; }
public int PlayerUserId { get; set; }
public int PlayerIALevel { get; set; }
public int PlayerObserver { get; set; }
}
var data = @"{
""game"":{""GameMode"":""1"",""IsNetworkMode"":""1"",""NbMaxPlayer"":""12"",""GameState"":""1""},
""player_56"":{""PlayerUserId"":""137187"",""PlayerIALevel"":""-1"",""PlayerObserver"":""0""},
""player_7"":{""PlayerUserId"":""3440"",""PlayerIALevel"":""-1"",""PlayerObserver"":""0""}
}";
JObject o = JObject.Parse(data);
IEnumerable<Player> players =
o.Children()
.Where(p => ((JProperty)p).Name.StartsWith("player"))
.Select(p =>
new Player
{
Id = int.Parse(((JProperty)p).Name.Split('_')[1]),
PlayerUserId = int.Parse((string)p.Children<JObject>().First()["PlayerUserId"]),
PlayerIALevel = int.Parse((string)p.Children<JObject>().First()["PlayerIALevel"]),
PlayerObserver = int.Parse((string)p.Children<JObject>().First()["PlayerObserver"]),
});