简体   繁体   English

将对象序列化为已经包含一个 JSON 属性的 JSON

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

In order to increase performance, I have cached the result of a larger operation as JSON in a table - together with a key column to determine which row(s) to return.为了提高性能,我将更大操作的结果作为 JSON 缓存在一个表中 - 连同一个键列来确定要返回的行。 So the data looks some like this:所以数据看起来像这样:

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

Hence, my retrieved object has the properties int .Id and string .Json .因此,我检索到的对象具有属性 int .Id和 string .Json When returning such an object with the Id, I first need to deserialize the JSON - so that it gets properly re-serialized.当使用 Id 返回这样的对象时,我首先需要反序列化 JSON - 以便正确地重新序列化。 If I don't deserialize it first, I end up with a quoted string, ie my return object would look like this如果我不先反序列化它,我最终会得到一个带引号的字符串,即我的返回对象看起来像这样

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

Instead, I need:相反,我需要:

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

Is there a way to "tell" the Json.Net serializer to output the .Json property directly without serializing - while serializing the other properties?有没有办法“告诉” Json.Net 序列化器直接输出.Json属性而不序列化 - 同时序列化其他属性?

You could make a JsonConverter to write the raw value of the string property to the output without changing it.您可以使用JsonConverter将字符串属性的原始值写入输出而不更改它。 You take responsibility for ensuring the string has valid JSON or else the resulting output will not be valid JSON either.您负责确保字符串具有有效的 JSON,否则结果输出也不是有效的 JSON。

Here is what the converter might look like:以下是转换器的外观:

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);  
    }
}

To use it, mark your JSON property with a [JsonConverter] attribute like this:要使用它,请使用[JsonConverter]属性标记您的 JSON 属性,如下所示:

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

Here is a demo: https://dotnetfiddle.net/BsTLO8这是一个演示: https : //dotnetfiddle.net/BsTLO8

Assuming you have a structure like this for serializing: 假设您有一个这样的结构用于序列化:

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

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

And you use code like this for serialization: 你使用这样的代码进行序列化:

    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);

All you need is to write a proper converter for the Json property. 您只需要为Json属性编写适当的转换器。 Luckily there is a method WriteToken in the JsonWriter class that could serve our needs: 幸运的是, 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);
    }
}

Based on answer by Alex and comment by Shahin, I improved the converter a bit, and also implemented the reader to work also the other way (parse back from JToken to the string property): 基于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.

相关问题 如何使用包含图像属性的 json.net 将 object 序列化为 json - How do I Serialize object to json using json.net which contains an image property JSON.NET:将 json 字符串属性序列化为 json 对象 - JSON.NET: Serialize json string property into json object 使用catch all dictionary属性将json序列化为一个对象 - Serialize json to an object with catch all dictionary property 使用“多类型”属性序列化 Json object - Serialize Json object with "multi-type" property 在Json中序列化没有属性名称的对象 - Serialize Object in Json without the property name 将包含对象属性的poco序列化为Json - Serialize poco containing object property into Json 将对象数组作为一个对象序列化,并在C#中使用JSON序列化程序为每个对象指定一个命名属性 - Serialize array of objects as one object with a named property for each object in C# with JSON serializer 序列化为JSON以每行获取一个对象 - Serialize to JSON to get one object per line 如何使用Property IList进行json序列化或json deserilize对象 <IOBJ> ? - How to json serialize or json deserilize object with Property IList<IOBJ>? 如何将具有多个字符串属性的对象序列化为每个具有一个字符串属性的对象的 json 数组? - How to serialize an object with multiple string properties to a json array of objects with one string property each?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM