2014-01-13 61 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