2014-01-13 3 views
1

JSON.NET을 사용하여 특정 JSON 문자열을 Dictionary<T, T2>에 매핑하는 데 문제가 있습니다.일련의 동일한 JSON 객체를 사전에 매핑

내 JSON 문자열은 다음과 같습니다

, 내가 그들 모두를 위해 작동 한 클래스 Asset 만든 오히려 각 개체에 대해 3 개 동일한 클래스를 만드는 것보다
{ 
    "map_waypoint": { "file_id": 157353, "signature": "32633AF8ADEA696A1EF56D3AE32D617B10D3AC57" }, 
    "map_waypoint_contested": { "file_id": 102349, "signature": "5EF051273B40CFAC4AEA6C1F1D0DA612C1B0776C" }, 
    "map_waypoint_hover": { "file_id": 157354, "signature": "95CE3F6B0502232AD90034E4B7CE6E5B0FD3CC5F" } 
} 

:

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 인 경우 FilesDictionary<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); 
} 

어떻게 든이 일을 할 수 있습니까?

답변

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는 Btw는

편집 작동하지 않습니다. 귀하의 데이터가 정확하지 않습니다. 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

관련 문제