2014-01-13 62 views
1

我在使用JSON.NET将某个JSON字符串映射到Dictionary<T, T2>时遇到问题。将一系列相同的JSON对象映射到字典

我的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,我保留Dictionary<String, Asset>类型的属性Files

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); 
} 

我可以做这项工作不知何故?

回答

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); 
+0

你说得对。但我真的很想做'result2'工作。 –

+0

感谢您指出这些签名不是GUID。我的印象是他们是,但他们不是。 –

+0

@Steven Liekens:FilesResponse是否可以从字典继承? – SOReader