C#JSON.NET - 反序列化使用不寻常数据结构的响应

时间:2016-09-13 02:48:23

标签: c# .net json serialization json.net

我在查找以特定格式反序列化某些JSON数据的干净(尽可能)方法时遇到了一些麻烦。我想将数据反序列化为强类型数据对象类,关于此的具体细节非常灵活。以下是数据的示例:

{
    "timestamp": 1473730993,
    "total_players": 945,
    "max_score": 8961474,
    "players": {
            "Player1Username": [
            121,
            "somestring",
            679900,
            5,
            4497,
            "anotherString",
            "thirdString",
            "fourthString",
            123,
            22,
            "YetAnotherString"],
        "Player2Username": [
            886,
            "stillAstring",
            1677,
            1,
            9876,
            "alwaysAstring",
            "thirdString",
            "fourthString",
            876,
            77,
            "string"]
        }
}

我不确定的具体部分是:

  1. 球员的集合会被视为字典吗?用户名可以作为密钥,但是这个值会让我失望,因为它会是字符串和整数值的混合集合。
  2. 玩家完全由未命名的值组成。我几乎总是使用已命名属性和值的JSON数据(例如,最顶层的timestamp,total_players等)
  3. 说我有这样的顶级课程:

    public class ScoreboardResults
    {
        public int timestamp { get; set; }
        public int total_players { get; set; }
        public int max_score { get; set; }
        public List<Player> players { get; set; }
    }
    

    Player对象看起来是什么样的,因为它基本上是用户名作为键的键/值,而值是混合整数和字符串的集合?每个玩家元素的数据总是以相同的顺序,所以我知道集合中的第一个值是他们的UniqueID,第二个值是玩家描述等。我希望玩家类是这样的:< / p>

    public class Player
    {
        public string Username { get; set; }
        public int UniqueID { get; set; }
        public string PlayerDescription { get; set; }
        ....
        ....
        .... Following this pattern for all of the values in each player element
        ....
        ....
    }
    

    我确信使用JSON.NET这是一件相当简单的事情,这就是为什么我想要避免任何关于如何实现这一点的想法。我想出的将是不优雅的,并且可能在序列化过程中容易出错。

    修改

    以下是snow_FFFFFF建议的将过去用作JSON类时生成的类:

    public class Rootobject
    {
        public int timestamp { get; set; }
        public int total_players { get; set; }
        public int max_score { get; set; }
        public Players players { get; set; }
    }
    
    public class Players
    {
        public object[] Player1Username { get; set; }
        public object[] Player2Username { get; set; }
    }
    

    我不清楚的是如何在&#34;播放器&#34;中反序列化JSON数据? element作为List,Player1Username是Player对象上的简单字符串属性。至于混合字符串和整数的集合,我相信我可以将它们放到Player对象的各个属性中而不会出问题。

3 个答案:

答案 0 :(得分:3)

开始使用的一个好方法是让visual studio根据JSON生成你的类。打开一个空白的类文件,然后转到EDIT - &gt; PASTE SPECIAL - &gt; PASTE JSON作为CLASSES。

这将生成一个包含必要类的文件,以序列化/反序列化您的JSON。

答案 1 :(得分:2)

来自Deserializing JSON in Visual Basic .NET的转换器应该做你需要的,适当地从VB.NET翻译成c#:

public class ObjectToArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(T) == objectType;
    }

    static bool ShouldSkip(JsonProperty property)
    {
        return property.Ignored || !property.Readable || !property.Writable;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var type = value.GetType();
        var contract = serializer.ContractResolver.ResolveContract(type) as JsonObjectContract;
        if (contract == null)
            throw new JsonSerializationException("invalid type " + type.FullName);
        var list = contract.Properties.Where(p => !ShouldSkip(p)).Select(p => p.ValueProvider.GetValue(value));
        serializer.Serialize(writer, list);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var token = JArray.Load(reader);
        var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonObjectContract;
        if (contract == null)
            throw new JsonSerializationException("invalid type " + objectType.FullName);
        var value = existingValue ?? contract.DefaultCreator();
        foreach (var pair in contract.Properties.Where(p => !ShouldSkip(p)).Zip(token, (p, v) => new { Value = v, Property = p }))
        {
            var propertyValue = pair.Value.ToObject(pair.Property.PropertyType, serializer);
            pair.Property.ValueProvider.SetValue(value, propertyValue);
        }
        return value;
    }
}

接下来,将转换器添加到Player类,并使用JsonPropertyAttribute.Order指示每个属性的顺序:

[JsonConverter(typeof(ObjectToArrayConverter<Player>))]
public class Player
{
    [JsonProperty(Order = 1)]
    public int UniqueID { get; set; }
    [JsonProperty(Order = 2)]
    public string PlayerDescription { get; set; }
    // Other fields as required.
}

最后,按如下方式声明您的根对象:

public class ScoreboardResults
{
    public int timestamp { get; set; }
    public int total_players { get; set; }
    public int max_score { get; set; }
    public Dictionary<string, Player> players { get; set; }
}

请注意,我已将Username移出Player类并作为键移入字典。

答案 2 :(得分:0)

试试这个

创建一个类如下

注意:您可以在visual studio中使用“选择性粘贴”选项来生成与JSON相关的所有类

编辑 - &gt;选择性粘贴 - &gt;将Json粘贴为类

它将创建与JSON相关的所有类

注意:请参考this我已经回复了类似的内容..