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

C# 将对象序列化为已包含一个JSON属性的JSON,c#,.net,asp.net-web-api,json.net,C#,.net,Asp.net Web Api,Json.net,为了提高性能,我将一个较大操作的结果作为JSON缓存在一个表中,并使用一个键列来确定返回哪一行。因此,数据如下所示: Id Json ---- --------- 1 {"property": "data", "...": "..."} 2 {"property": "data", "...": "..."} class Foo { ... [JsonConverter(typeof(RawJsonConverter))] public string Y

为了提高性能,我将一个较大操作的结果作为JSON缓存在一个表中,并使用一个键列来确定返回哪一行。因此,数据如下所示:

Id   Json
---- ---------
1    {"property": "data", "...": "..."}
2    {"property": "data", "...": "..."}
class Foo
{
    ...
    [JsonConverter(typeof(RawJsonConverter))]
    public string YourJsonProperty { get; set; }
    ...
}
因此,我检索到的对象具有int
.Id
和string
.Json
属性。当返回这样一个Id为的对象时,我首先需要对JSON进行反序列化,以便正确地重新序列化它。如果我不先反序列化它,我将得到一个带引号的字符串,即我的返回对象如下所示

{
  "id": 1,
  "json": "{\"property\": \"data\", ...
}
相反,我需要:

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

有没有一种方法可以“告诉”Json.Net序列化程序直接输出
.Json
属性而不进行序列化-同时序列化其他属性?

假设您有这样一种用于序列化的结构:

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

您可以创建一个
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属性,如下所示:

Id   Json
---- ---------
1    {"property": "data", "...": "..."}
2    {"property": "data", "...": "..."}
class Foo
{
    ...
    [JsonConverter(typeof(RawJsonConverter))]
    public string YourJsonProperty { get; set; }
    ...
}
下面是一个演示:

基于Shahin的分析和评论,我对转换器做了一些改进,还实现了阅读器以另一种方式工作(从JToken解析回string属性):


因此,如果我理解您的输出是{“id”:1,“Json”:{“data1”:“value”,“data2”:“value”,“data3”:“value”},而您想要的是{“id”:1,“Json”:“data1\”:“value\”,“data2\”:“value\”,“data3\”:“value\”。@VeNoMiS:查看更新的问题,我认为您需要为该类型编写自己的JsonConverter。使用2类(容器和项目)具有2个属性(int-id和Item-json)和带有属性的项的容器。Item m=JsonConvert.DeserializeObject(row.json)应该执行以下操作:您确定它是有效的json吗?如果不希望Json.NET转义,则必须是有效的。我想补充一点,您也可以在WriteJson中编写以下内容:
writer.WriteToken(JsonToken.Raw,value)
writer.WriteRawValue((字符串)值)如图所示会更简单。