在ASP.NET Web API应用程序中,我使用的一些模型包含一大块ad-hoc 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
}
}
理想情况下,这适用于两个方向,即在POST JSON表示时,它将自动反序列化为上面的C#表示。
使用Json.NET实现这一目标的最佳机制是什么?我是否需要自定义JsonConverter
?是否有一个更简单的基于属性的机制?效率很重要;重点是跳过序列化开销,可以进行一些微优化,但为了论证,我们假设它没有。 (可能会返回包含大量Json
属性的大型列表。)
答案 0 :(得分:17)
如果您能够将Json
的{{1}}属性类型从Person
更改为string
,那么您将获得所需的结果。
JRaw
或者,您可以保留public class Person
{
public string FirstName { get; set;}
public string LastName { get; set;}
public JRaw Json { get; set;}
}
属性,并添加string
属性以用作序列化的代理:
JRaw
无论哪种方式,序列化和反序列化都可以按照您的要求运行。
答案 1 :(得分:1)
我不确定这是一件非常有用的事情,但您可以创建一个这样的自定义转换器:
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);
}
}
现在,如果您使用Json
装饰[JsonConverter(typeof(StringToJsonConverter))]
属性,则可以执行以下操作:
var obj = new Person
{
FirstName = "John",
LastName = "Smith",
Json = "{ \"Age\": 30 }"
};
var s = JsonConvert.SerializeObject(obj);
得到这个:
{"FirstName":"John","LastName":"Smith","Json":{"Age":30}}
这是{{3}}
然而,在我的小提琴中,我注意到了序列化和反序列化,但Json
属性中的值并不完全相同。为什么?因为花括号周围的额外空间在此过程中被剥离了。当然,它们不是(或不应该)重要的。
答案 2 :(得分:0)
我不确定是否有办法跳过序列化。这是一个以简单方式序列化和反序列化的选项。
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); } }
}