C# 是否可以将对象序列化为与使用Json.Net反序列化不同的方式?

C# 是否可以将对象序列化为与使用Json.Net反序列化不同的方式?,c#,serialization,json.net,C#,Serialization,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

以下是我的例子:

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 identifier属性找到实际的实体,用找到的实体填充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]标记实体,如下所示:

[ScriptIgnore]
[JsonIgnore]
public EntityObject Entity { get; set; }
我听说杰索尼诺有时不工作。两者都使用可能是你最好的选择

另外,我相信你在描述问题时的措辞是不正确的。您声明:“这是我在反序列化对象时得到的结果”——实际上,我相信您的意思是“序列化”

如果需要在设置EntityIdentifier时填充实体,请将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对象序列化为文件。这里的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]
属性修饰
请求
类,如下所示。请注意,您可以删除private
EntityIdentifier
属性,因为不再需要它。转换器负责根据JSON中的标识符从数据库中检索
EntityObject

[JsonConverter(typeof(RequestConverter))]
public class Request
{
    public Request() { }

    public EntityObject Entity { get; set; }
}

注意,如果您不想让转换器负责填充实体对象,您仍然可以使用转换器的思想。在这种情况下,让
ReadJson
方法在请求上设置
EntityIdentifier
属性。但是,由于您已将此属性设置为私有属性,因此您需要使用反射来完成此操作,将属性设置为公共属性,或者为转换器可以使用标识符实例化的请求设置构造函数。

也许您只需要确定JSON.Net无法序列化EntityObject的原因(例如无限递归)您是否只需要将您的
实体
属性标记为未序列化?如果这是检索正确项的方式,则需要序列化id。当您反序列化时,只需从结果返回实体(对象),而不是整个请求?这并不是我不希望实体属性序列化,或者存在错误……简单地说,我想要的是“当仅反序列化写入[EntityIdentifier]时,当仅序列化[Entity]时,但这两个属性都作为[entity]“,这更有意义吗?您或我的术语有误。仅将id用作名称您可以反序列化您的对象,并且您不必担心它?对不起,是的,我的意思是序列化,现在将更改它。不起作用,因为当我序列化它时,entity将是字符串而不是对象,这不符合我在下指定的内容“当我真正想要的是:"。如果您阅读了我在最初帖子下的评论,这可能也会为您澄清这一点。因此-反序列化时,您只想查看实体ID,但序列化时,您想输出所有实体属性?这没有多大意义。实际上,实体应该知道自己的ID-并且在请求sho中为其指定单独的属性不需要。请参阅我的编辑,实体ID位于请求对象上,实体对象位于请求对象上。我不是在实体对象上指定实体ID,而是在请求对象上指定实体ID,然后运行一些代码,使用请求对象上的实体ID填充实体对象。希望这是有意义的。但是当我现在反序列化字符串时,这将不起作用,因为字符串无法转换为EntityObject。谢谢,但我在最初的帖子中已经说过,我可以拆分这些内容,但如果有其他方法,那会更好(对我来说),否则我将不得不走这条路。像这样拆分实体将是一种干净、快速、可读和可维护的方式,可以让您想要的数据进出您的系统。您的OP是一个很好的问题,因为它突出了在常见用例中使用JSON.NET可以和不能做什么,但感觉您正在尝试适应一个正方形当你有一个圆钉可用时,把它钉在一个圆孔里。