簡體   English   中英

將對象序列化為已經包含一個 JSON 屬性的 JSON

[英]Serialize object to JSON that already contains one JSON property

為了提高性能,我將更大操作的結果作為 JSON 緩存在一個表中 - 連同一個鍵列來確定要返回的行。 所以數據看起來像這樣:

Id   Json
---- ---------
1    {"property": "data", "...": "..."}
2    {"property": "data", "...": "..."}

因此,我檢索到的對象具有屬性 int .Id和 string .Json 當使用 Id 返回這樣的對象時,我首先需要反序列化 JSON - 以便正確地重新序列化。 如果我不先反序列化它,我最終會得到一個帶引號的字符串,即我的返回對象看起來像這樣

{
  "id": 1,
  "json": "{\"property\": \"data\", ...
}

相反,我需要:

{
  "id": 1,
  "json": {
      "property": "data", 
      ...
  }
}

有沒有辦法“告訴” Json.Net 序列化器直接輸出.Json屬性而不序列化 - 同時序列化其他屬性?

您可以使用JsonConverter將字符串屬性的原始值寫入輸出而不更改它。 您負責確保字符串具有有效的 JSON,否則結果輸出也不是有效的 JSON。

以下是轉換器的外觀:

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // write value directly to output; assumes string is already JSON
        writer.WriteRawValue((string)value);  
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // convert parsed JSON back to string
        return JToken.Load(reader).ToString(Formatting.None);  
    }
}

要使用它,請使用[JsonConverter]屬性標記您的 JSON 屬性,如下所示:

class Foo
{
    ...
    [JsonConverter(typeof(RawJsonConverter))]
    public string YourJsonProperty { get; set; }
    ...
}

這是一個演示: https : //dotnetfiddle.net/BsTLO8

假設您有一個這樣的結構用於序列化:

public class Record
{
    [JsonProperty("id")]
    public int Id
    {
        get;
        set;
    }

    [JsonProperty("json")]
    [JsonConverter(typeof(SpecialJsonConverter))]
    public string Json
    {
        get;
        set;
    }
}

你使用這樣的代碼進行序列化:

    var data = new []
    { 
        new Record() { Id=1, Json = "{\"property\":\"data\"}" }, 
        new Record() { Id=2, Json = "{\"property\":\"data2\", \"property2\":[1, 2, 3]}" }
    };

    var serialized = JsonConvert.SerializeObject(data);
    Console.WriteLine(serialized);

您只需要為Json屬性編寫適當的轉換器。 幸運的是, JsonWriter類中有一個方法WriteToken可以滿足我們的需求:

public sealed class SpecialJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var reader = new JsonTextReader(new StringReader(value.ToString()));
        writer.WriteToken(reader);
    }
}

基於Alex的回答和Shahin的評論,我對轉換器進行了一些改進,並且還實現了讀取器以另一種方式工作(從JToken解析回字符串屬性):

public sealed class RawDataJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var tokenReader = reader as JTokenReader;
        var data = tokenReader.CurrentToken.ToString(Formatting.None);
        return data;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteToken(JsonToken.Raw, value);
    }
}

暫無
暫無

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

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