簡體   English   中英

C# 使用以字符串開頭的鍵名反序列化 JSON

[英]C# Deserialize JSON with Key Name Starting with String

我有一些看起來像這樣的 JSON:

{
    "fs_Unique_Form_Name": {
        "title": "Title Text",
        "description": "This is the description.",
        "code": "123"
    },
    "stackId": 1,
    "stateId": 1,
    "timeStamp": "2020-11-04:10.30.48"
} 

我正在使用 Newtonsoft.Json 嘗試將其反序列化為模型對象,但我很難使用動態鍵; 如果可能,我想使該屬性通用,因為內部對象始終相同。

以下是我嘗試使用的模型:

public class FormDetail {
    [JsonProperty(PropertyName = "title")]
    public string Title { get; set; }

    [JsonProperty(PropertyName = "description")]
    public string Description { get; set; }

    [JsonProperty(PropertyName = "code")]
    public string Code { get; set; }
}

public class FormResponse {
    [JsonProperty(PropertyName = "NEED TO FIGURE THIS OUT")]
    public FormDetail FormDetail { get; set; }

    [JsonProperty(PropertyName = "stackId")]
    public int StackId { get; set; }

    [JsonProperty(PropertyName = "stateId")]
    public int StateId { get; set; }

    [JsonProperty(PropertyName = "timeStamp")]
    public string TimeStamp { get; set; }
}

我想將整個 JSON 反序列化為FormResponse對象,但我遇到了困難,因為fs_Unique_Form_Name鍵在fs_部分之后是動態的,但該對象中的鍵(標題、描述、代碼)是靜態的。

當 JSON 鍵以fs_開頭時,有沒有辦法讓我可以將其反序列化為FormDetail屬性?

您可以通過為您的FormResponse類制作自定義JsonConverter來做到這一點。 以下是轉換器所需的代碼:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Load the JSON into a JObject so we can inspect it.
        JObject obj = JObject.Load(reader);

        // Populate all the known properties on a new instance of FormResponse.
        FormResponse response = new FormResponse();
        serializer.Populate(obj.CreateReader(), response);

        // Now find the first property in the JObject whose name starts with "fs_".
        // If there is one, use it to populate the FormDetail on the response.
        JProperty prop = obj.Properties().FirstOrDefault(p => p.Name.StartsWith("fs_"));
        response.FormDetail = prop != null ? prop.Value.ToObject<FormDetail>(serializer) : null;

        return response;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用轉換器,請將[JsonConverter]屬性添加到您的FormResponse類,如下所示。 您可以從FormDetail屬性中刪除[JsonProperty]屬性,因為它不需要。

[JsonConverter(typeof(FormResponseConverter))]
public class FormResponse
{
    public FormDetail FormDetail { get; set; }

    [JsonProperty(PropertyName = "stackId")]
    public int StackId { get; set; }

    [JsonProperty(PropertyName = "stateId")]
    public int StateId { get; set; }

    [JsonProperty(PropertyName = "timeStamp")]
    public string TimeStamp { get; set; }
}

然后你可以像往常一樣反序列化:

var response = JsonConvert.DeserializeObject<FormResponse>(json);

這是一個工作演示: https : //dotnetfiddle.net/jHyRcK

有很多方法可以做到。

例如,讓我們創建一個自定義閱讀器。

class CustomJsonReader : JsonTextReader
{
    public CustomJsonReader(TextReader reader) : base(reader) { }

    public override object Value
    {
        get
        {
            if (base.TokenType == JsonToken.PropertyName &&
                base.Value.ToString().StartsWith("fs_"))
                return "FormDetail";

            return base.Value;
        }
    }
}

像這樣使用它

FormResponse response;
var serializer = JsonSerializer.CreateDefault();

using (var streamReader = new StreamReader("test.json"))
using (var jsonReader = new CustomJsonReader(streamReader))
{
    response = serializer.Deserialize<FormResponse>(jsonReader);
}

在這種情況下, FormDetail屬性不需要JsonProperty屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM