[英]Is it possible to serialize an object differently to deserializing it using Json.Net?
这是我的示例:
JSON请求字符串:
{
entity: '09f7cb28-0464-41c8-a20d-1b05eb1cda0a'
}
我的请求对象:
public class Request {
public Request() { }
[JsonProperty("entity")]
private string EntityIdentifier { get; set; }
public EntityObject Entity { get; set; }
}
我已经做到这一点,以便将字符串传递给EntityIdentifier,这很好,然后在我的代码中,我使用实体标识符属性找到了实际的实体,并使用找到的实体填充了Entity属性,但这就是我所要做的当我序列化对象时得到:
{
entity: '09f7cb28-0464-41c8-a20d-1b05eb1cda0a',
Entity: {
// my object's properties
}
}
我真正想要的是:
{
entity: {
// my object's properties
}
}
现在,我知道我可以将其分为两个不同的类,也许必须这样做,但是如果有一种方法可以将它们全部保留在同一个类中,那将会很棒,并且可以节省很多编码时间。
需要澄清,因为我似乎没有很好地解释我想要的东西:
免责声明:这不存在(AFAIK),但这是我想要的:
public class Request {
public Request() { }
[JsonProperty("entity", OnlyWhen=Deserializing)]
private string EntityIdentifier { get; set; }
[JsonProperty("entity", OnlyWhen=Serializing)]
public EntityObject Entity { get; set; }
}
这是我真正想要实现的目标,但是据我所知,我可以将这种类型的代码实际放在唯一的位置是自定义转换器,但是不幸的是,我似乎无法确定转换器是否使用序列号时将其用于序列化或反序列化。
我相信您只需要用[ScriptIgnore]和/或[JsonIgnore]标记Entity,如下所示:
[ScriptIgnore]
[JsonIgnore]
public EntityObject Entity { get; set; }
我听说JsonIgnore有时无法正常工作。 最好同时使用两者。
另外-我认为您在描述问题时的措辞不正确。 您声明:“这是我对对象进行反序列化时得到的”-实际上,我相信您的意思是说“序列化”。
如果在设置EntityIdentifier时需要填充Entity,则将EntityIdentifier的代码替换为以下内容:
string _eId;
[JsonProperty("entity")]
private string EntityIdentifier
{
get{return _eId;}
set
{
_eId = value;
Entity = someMethodToRetrieveTheEntityById(_eId);
}
}
如何使用JsonIgnore属性?
public class Request
{
public Request() { }
[JsonIgnore]
private string EntityIdentifier { get; set; }
[JsonProperty("entity")]
public EntityObject Entity { get; set; }
}
这里的问题可能是您试图迫使一堂课做两堂课。 为什么不这样做:
// Deserialize requests into this.
public class EntityRequest
{
[JsonProperty("entity")]
private string EntityIdentifier { get; set; }
}
// Serialize these to file/etc.
public class EntityData
{
[JsonProperty("entity")]
public EntityObject Entity { get; set; }
}
然后,您将请求反序列化为EntityRequest对象,使用EntityRequest和其他逻辑加载EntityData对象,然后将EntityData对象序列化为file。 这里的JsonProperty属性意味着请求和输出实体都被称为“实体”,就像在OP中一样。 这似乎是您要遵循的工作流程。
将所有事物塞到一类中会使这个问题变得更加复杂。
您可以使用类似于以下内容的自定义JsonConverter
解决此问题:
public class RequestConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Request));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// On deserialization, the JSON has an entity identifier (GUID)
// so use it to retrieve the actual object from the database.
JToken token = JToken.Load(reader);
Request req = new Request();
req.Entity = RetrieveFromDatabase(token["entity"].ToString());
return req;
}
private EntityObject RetrieveFromDatabase(string entityIdentifier)
{
// Implement this method to retrieve the actual EntityObject from the DB.
// (Return null if the object is not found.)
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// On serialization, write out just the entity object properties
Request req = (Request)value;
JObject obj = new JObject();
obj.Add("entity", JToken.FromObject(req.Entity));
obj.WriteTo(writer);
}
}
要使用转换器,只需使用[JsonConverter]
属性装饰您的Request
类,如下所示。 请注意,您可以删除私有的EntityIdentifier
属性,因为将不再需要它。 转换器负责根据JSON中的标识符从数据库中检索EntityObject
。
[JsonConverter(typeof(RequestConverter))]
public class Request
{
public Request() { }
public EntityObject Entity { get; set; }
}
请注意,如果您不希望转换器负责填充实体对象,则仍然可以使用转换器思想。 在这种情况下,使ReadJson
方法在请求上设置EntityIdentifier
属性。 但是,由于已将此属性设为私有,因此您将需要使用反射来做到这一点,将该属性设为公共,或者为Request创建一个构造函数,转换器可以使用该构造函数将该标识符实例化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.