Json.防止重新序列化已经序列化的属性

本文关键字:序列化 属性 Json | 更新日期: 2023-09-27 18:15:00

. NET Web API应用程序,我正在使用的一些模型包含一大块仅在客户端有用的临时JSON。在服务器上,它只是作为字符串进出关系数据库。性能是关键,在服务器端处理JSON字符串似乎毫无意义。

在c#中,想象一个这样的对象:

new Person
{
    FirstName = "John",
    LastName = "Smith",
    Json = "{ '"Age'": 30 }"
};

默认为Json。. NET将像这样序列化这个对象:

{
    "FirstName": "John",
    "LastName": "Smith",
    "Json": "{ '"Age'": 30 }"
}

我想能够指导Json。. NET假定Json属性已经是一个序列化的表示,因此它不应该重新序列化,结果JSON应该是这样的:

{
    "FirstName": "John",
    "LastName": "Smith",
    "Json": {
        "Age": 30
    }
}

理想情况下,这是双向的,也就是说,当发布JSON表示时,它会自动反序列化为上面的c#表示。

在Json.NET中实现这一点的最佳机制是什么?我需要自定义JsonConverter吗?有没有更简单的基于属性的机制?效率问题;关键是要跳过序列化开销,可能是一个微优化,但为了讨论,我们假设它不是。(可能会返回大量Json属性的大列表。)

Json.防止重新序列化已经序列化的属性

如果您能够将Person上的Json属性的类型从string更改为JRaw,那么您将获得所需的结果。

public class Person
{
    public string FirstName { get; set;}
    public string LastName { get; set;}        
    public JRaw Json  { get; set;}
} 

或者,您可以保留string属性,并添加JRaw属性作为序列化的代理:

public class Person
{
    public string FirstName { get; set;}
    public string LastName { get; set;}
    [JsonIgnore]
    public string Json { get; set; }
    [JsonProperty("Json")]
    private JRaw MyJson
    {
        get { return new JRaw(this.Json); }
        set { this.Json = value.ToString(); }
    }        
}

无论哪种方式,序列化和反序列化都将按照您的要求工作。

我不确定这到底是一个有用的事情,但你可以创建一个自定义转换器,像这样:

public class StringToJsonConverter : JsonConverter
{
    public override bool CanConvert(Type t)
    {
        throw new NotImplementedException();
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var o = JsonConvert.DeserializeObject(value.ToString());
        serializer.Serialize(writer,o);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var o = serializer.Deserialize(reader);
        return JsonConvert.SerializeObject(o);
    }
}

现在,如果你用[JsonConverter(typeof(StringToJsonConverter))]来装饰Json属性,你可以这样做:

var obj = new Person
{
    FirstName = "John", 
    LastName = "Smith", 
    Json = "{ '"Age'": 30 }"
};
var s = JsonConvert.SerializeObject(obj);

得到这个:

{"FirstName":"John","LastName":"Smith","Json":{"Age":30}}

Here's a fiddle

一个注意事项,然而,在我的fiddle,我往返序列化和反序列化,但在Json属性的值是不完全相同的。为什么?因为在这个过程中,花括号周围的额外空格已经被去掉了。当然,它们不是(或不应该是)重要的。

我不确定是否有办法跳过这段序列化。这里有一个以简单方式序列化和反序列化的选项。

public class Person
{
    public string FirstName = "John";
    public string LastName = "Smith";
    [JsonIgnore]
    public string Json = "{ '"Age'": 30 }";
    public JObject JsonP { get { return JsonConvert.DeserializeObject<JObject>(Json); } }
}