将一系列相同的JSON对象映射到字典

时间:2014-01-13 23:27:38

标签: c# json json.net

我无法使用JSON.NET将某个JSON字符串映射到Dictionary<T, T2>

我的JSON字符串如下所示:

{
  "map_waypoint": { "file_id": 157353, "signature": "32633AF8ADEA696A1EF56D3AE32D617B10D3AC57" },
  "map_waypoint_contested": { "file_id": 102349, "signature": "5EF051273B40CFAC4AEA6C1F1D0DA612C1B0776C" },
  "map_waypoint_hover": { "file_id": 157354, "signature": "95CE3F6B0502232AD90034E4B7CE6E5B0FD3CC5F" }
}

我没有为每个对象创建3个相同的类,而是创建了适用于所有对象的1个类Asset

public class Asset
{
    /// <summary>
    /// Initializes a new instance of the <see cref="Asset"/> class.
    /// </summary>
    public Asset()
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Asset"/> class.
    /// </summary>
    /// <param name="fileId">The file ID.</param>
    /// <param name="signature">The file signature.</param>
    [JsonConstructor]
    public Asset(string fileId, string signature)
    {
        this.FileId = fileId;
        this.Signature = signature;
    }

    /// <summary>
    /// Gets the file ID to be used with the render service.
    /// </summary>
    [JsonProperty("file_id")]
    public string FileId { get; private set; }

    /// <summary>
    /// Gets file signature to be used with the render service.
    /// </summary>
    [JsonProperty("signature")]
    public string Signature { get; private set; }

    /// <summary>
    /// Gets the JSON representation of this instance.
    /// </summary>
    /// <returns>Returns a JSON <see cref="String"/>.</returns>
    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

现在在另一个班级FilesResponse中,我保留了Files类型的属性Dictionary<String, Asset>

public class FilesResponse
{
    /// <summary>
    /// Initializes a new instance of the <see cref="FilesResponse"/> class.
    /// </summary>
    public FilesResponse()
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="FilesResponse"/> class.
    /// </summary>
    /// <param name="files">A collection of assets by their name.</param>
    [JsonConstructor]
    public FilesResponse(Dictionary<string, Asset> files)
    {
        this.Files = files;
    }

    /// <summary>
    /// Gets the collection of assets by their name.
    /// </summary>
    [JsonProperty]
    public Dictionary<string, Asset> Files { get;  private set; }

    /// <summary>
    /// Gets the JSON representation of this instance.
    /// </summary>
    /// <returns>Returns a JSON <see cref="String"/>.</returns>
    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

问题是我不太确定如何让JSON.NET知道我的JSON字符串中的数据应该进入字典...?

理想情况下,我希望能够做到这一点:

var filesResponse = JsonConvert.DeserializeObject<FilesResponse>(jsonString);

foreach (var file in filesResponse.Files)
{
    Console.WriteLine("Name = {0}, ID = {1}", file.Key, file.Value.FileId);
}

我能以某种方式完成这项工作吗?

1 个答案:

答案 0 :(得分:0)

如果您想拥有GUID,则需要实现自己的转换器。我最终得到了这样的东西。

public class StringGuidConverter: JsonConverter {
    public override bool CanConvert(Type objectType) {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        return new Guid((string)reader.Value);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        writer.WriteValue(((Guid)value).ToString("N"));
    }
}

public class Asset {
    /// <summary>
    /// Initializes a new instance of the <see cref="Asset"/> class.
    /// </summary>
    public Asset() {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Asset"/> class.
    /// </summary>
    /// <param name="fileId">The file ID.</param>
    /// <param name="signature">The file signature.</param>
    [JsonConstructor]
    public Asset(string fileId, Guid signature) {
        this.FileId = fileId;
        this.Signature = signature;
    }

    /// <summary>
    /// Gets the file ID to be used with the render service.
    /// </summary>
    [JsonProperty("file_id")]
    public string FileId { get; private set; }

    /// <summary>
    /// Gets file signature to be used with the render service.
    /// </summary>
    [JsonProperty("signature")]
    [JsonConverter(typeof(StringGuidConverter))]
    public Guid Signature { get; private set; }

    /// <summary>
    /// Gets the JSON representation of this instance.
    /// </summary>
    /// <returns>Returns a JSON <see cref="String"/>.</returns>
    public override string ToString() {
        return JsonConvert.SerializeObject(this);
    }
}

public class FilesResponse {
    /// <summary>
    /// Initializes a new instance of the <see cref="FilesResponse"/> class.
    /// </summary>
    public FilesResponse() {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="FilesResponse"/> class.
    /// </summary>
    /// <param name="files">A collection of assets by their name.</param>
    [JsonConstructor]
    public FilesResponse(Dictionary<string, Asset> files) {
        this.Files = files;
    }

    /// <summary>
    /// Gets the collection of assets by their name.
    /// </summary>
    [JsonProperty]
    public Dictionary<string, Asset> Files { get; private set; }

    /// <summary>
    /// Gets the JSON representation of this instance.
    /// </summary>
    /// <returns>Returns a JSON <see cref="String"/>.</returns>
    public override string ToString() {
        return JsonConvert.SerializeObject(this);
    }
}

class Test {
    public static void Run() {
        var json = @"{
  ""map_waypoint"": { ""file_id"": 157353, ""signature"": ""32633AF8ADEA696AE32D617B10D3AC57"" },
  ""map_waypoint_contested"": { ""file_id"": 102349, ""signature"": ""32633AF8ADEA696AE32D617B10D3AC57"" },
  ""map_waypoint_hover"": { ""file_id"": 157354, ""signature"": ""32633AF8ADEA696AE32D617B10D3AC57"" }
}";


        var result2 = JsonConvert.DeserializeObject<FilesResponse>(json);
        var result3 = new FilesResponse(JsonConvert.DeserializeObject<Dictionary<string, Asset>>(json));
    }
}

Unfotunatelly result2不起作用

修改 顺便说一句。你的数据不正确。 GUID长度为32个字符,长度为40个字符。这就是我必须修改测试数据的原因。

<强> EDIT2

我会使FilesResponse继承自字典,如下所示:

public class FilesResponse2: Dictionary<string, Asset>
{
    /// <summary>
    /// Initializes a new instance of the <see cref="FilesResponse"/> class.
    /// </summary>
    public FilesResponse2() {
    }

    /// <summary>
    /// Gets the collection of assets by their name.
    /// </summary>
    public Dictionary<string, Asset> Files { get { return this; } }

    /// <summary>
    /// Gets the JSON representation of this instance.
    /// </summary>
    /// <returns>Returns a JSON <see cref="String"/>.</returns>
    public override string ToString() {
        return JsonConvert.SerializeObject(this);
    }
}

// deserialization:
var result22 = JsonConvert.DeserializeObject<FilesResponse2>(json);