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

C# 将一系列相同的JSON对象映射到字典,c#,json,json.net,C#,Json,Json.net,我在使用JSON.NET将某个JSON字符串映射到字典时遇到问题 我的JSON字符串如下所示: { "map_waypoint": { "file_id": 157353, "signature": "32633AF8ADEA696A1EF56D3AE32D617B10D3AC57" }, "map_waypoint_contested": { "file_id": 102349, "signature": "5EF051273B40CFAC4AEA6C1F1D0DA612C1B0776

我在使用JSON.NET将某个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" }
}
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);
我没有为每个对象创建3个相同的类,而是创建了一个适用于所有对象的类
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);
    }
}
问题是,我不太确定如何让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);
}
var filesResponse=JsonConvert.DeserializeObject(jsonString);
foreach(filesResponse.Files中的var文件)
{
WriteLine(“Name={0},ID={1}”,file.Key,file.Value.FileId);
}

我能以某种方式实现这一点吗?

如果你想拥有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));
    }
}

你说得对。但是我真的,真的想让
result2
起作用。谢谢你指出这些签名不是guid。史蒂文·列肯斯:FileResponse有可能从字典继承吗?是的,我知道我可以做到这一点。或者,我可以为每个对象创建一个
Asset
类型的属性,并使用
[JsonPropertyAttribute]
标记这些属性。但实际上,我更希望所有数据都放在一个
文件
字典中。你知道吗?如果开发人员希望我使用集合类型,他们应该将JSON设计成一个数组。我将继续为每个对象分别添加一个属性。
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);