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

时间:2013-06-18 16:05:26

标签: c# json collections deserialization

我必须将给定的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"}
}

我想将Player实体序列化为此类对象的集合。问题是它们并不真正存储为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; }
}

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

将您的JSON剪切为一组玩家对象。

player_8: {...}
player_99: {...}

players: [
    {id: 8 ...},
    {id: 99 ...}
]

如何破坏你的JSON,RegEx可能就足够了。

编辑这是使用Regex进行字符串修改的代码。做了一些假设:游戏和玩家对象中没有嵌入对象,玩家对象列表是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对象设置为静态且可重复使用将是我的第一步,如果我必须优化上述步骤。

答案 1 :(得分:1)

我不知道DataContractJsonSerializer的范围,但您可以在类上实现一个接口来定义如何解析JSON。

但是如果你能够使用JSON.Net

public class Player
{
    public int Id { get; set; }
    public int PlayerUserId { get; set; }
    public int PlayerIALevel { get; set; }
    public int PlayerObserver { get; set; }
}

然后你可以使用Linq-To-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"]),
        });