. 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
属性的大列表。)
如果您能够将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); } }
}