Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JSON将不同的命名对象反序列化到集合c中#_C#_Json_Collections_Deserialization - Fatal编程技术网

C# JSON将不同的命名对象反序列化到集合c中#

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

我必须将给定的JSON字符串读入C#对象。到目前为止还不错,但这个案子对我来说有点特别。JSON字符串包含2个实体。一个是平面对象,第二个是列表,至少在JSON中是逻辑的,但实际上不是。我希望你能帮我找到解决办法

为了更好地解释,我将向您展示我的JSON输入的一部分:

{
"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"]),
        });