【问题标题】:How to set part of Json.Net JsonProperty attribute in a derived class without replacing the JsonProperty in the base?如何在派生类中设置 Json.Net JsonProperty 属性的一部分而不替换基类中的 JsonProperty?
【发布时间】:2019-08-12 14:31:55
【问题描述】:

我试图在基类中设置一个特定的 JsonProperty(名称),但也在派生类中设置另一个(不相关的)JsonProperty。不幸的是,这在序列化和反序列化期间似乎不起作用。派生类中的 JsonProperty 完全替代了基类中的 JsonProperty。

我怎样才能在派生类中仍然使用 JsonProperty 并且在序列化和反序列化期间仍然尊重基类中的 JsonProperty?

我有这个基类:

public class BaseNode
{
    [JsonProperty(PropertyName = "id", Required = Required.DisallowNull)]
    public string _sNodeId { get; set; }

    [JsonProperty(PropertyName = "parentid")]
    [DisplayName("Parent Folder")]
    [DefaultValue("000000000000000000000000")]
    [MaxLength(24)]
    [MinLength(24)]
    public virtual string _sNodeParentId { get; set; }
}

这个类派生自它:

public class BaseBoardNode : BaseNode
{
    [JsonProperty(PropertyName = "name")]
    [DisplayName("Name")]
    [Description("Logical name for board")]
    [DefaultValue("newboard")]
    [MinLength(1)]
    [MaxLength(128)]
    public virtual string _sNodeName { get; set; }

    [JsonProperty(PropertyName = "ip")]
    [DisplayName("IP")]
    [Description("IP(v4) to use to sync to this board")]
    [DefaultValue("192.168.1.1")]
    [RegularExpression("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")]
    public virtual string _sNodeIP { get; set; }

    [JsonProperty(PropertyName = "port")]
    [DisplayName("Port")]
    [Description("TCP port to use to sync to this board")]
    [DefaultValue(8080)]
    [MinLength(0)]
    [MaxLength(60000)]
    public virtual int _iNodePort { get; set; }

    [JsonProperty(PropertyName = "devicefamily", Required = Required.Default)]
    [DisplayName("Device Family (Read-Only)")]
    [Description("Device family of board (read-only)")]
    public string _sDeviceFamily { get; set; }
}

然后我有 2 个最终派生类(以后可能会更多):

public class DefaultingBoard : BaseBoardNode
{
    [JsonProperty(Required = Required.DisallowNull, DefaultValueHandling = DefaultValueHandling.Populate)]
    public override string _sNodeParentId { get => base._sNodeParentId; set => base._sNodeParentId = value; }

    [JsonProperty(Required = Required.DisallowNull, DefaultValueHandling = DefaultValueHandling.Populate)]
    public override string _sNodeName { get => base._sNodeName; set => base._sNodeName = value; }

    [JsonProperty(Required = Required.DisallowNull, DefaultValueHandling = DefaultValueHandling.Populate)]
    public override string _sNodeIP { get => base._sNodeIP; set => base._sNodeIP = value; }

    [JsonProperty(Required = Required.DisallowNull, DefaultValueHandling = DefaultValueHandling.Populate)]
    public override int _iNodePort { get => base._iNodePort; set => base._iNodePort = value; }
}

public class NonDefaultingBoard : BaseBoardNode
{
    [JsonProperty(Required = Required.Always)]
    public override string _sNodeParentId { get => base._sNodeParentId; set => base._sNodeParentId = value; }

    [JsonProperty(Required = Required.Always)]
    public override string _sNodeName { get => base._sNodeName; set => base._sNodeName = value; }

    [JsonProperty(Required = Required.Always)]
    public override string _sNodeIP { get => base._sNodeIP; set => base._sNodeIP = value; }

    [JsonProperty(Required = Required.Always)]
    public override int _iNodePort { get => base._iNodePort; set => base._iNodePort = value; }
}

当我序列化 DefaultingBoard 时,我得到了这个:

{
    "_sNodeParentId": "000000000000000000000000",
    "_sNodeName": "newboard",
    "_sNodeIP": "192.168.1.1",
    "_iNodePort": 8080,
    "devicefamily": null,
    "id": "5c93b4b33485788504fcbffb"
}

而不是这个期望的结果:

{
    "parentid": "000000000000000000000000",
    "name": "newboard",
    "ip": "192.168.1.1",
    "port": 8080,
    "devicefamily": null,
    "id": "5c93b4b33485788504fcbffb"
}

是否有一种直接的方法来获得所需的结果(即如何使 JsonProperty.PropertyName 不被覆盖或以某种方式从基础获得)?

【问题讨论】:

  • 你不能像在基类中那样给DefaultingBoard类属性_sNodeParentId一个名称别名吗?只需添加该装饰并将其设置为 parentid [JsonProperty(PropertyName = "parentid")]
  • @RyanWilson 我可以。唯一的问题是,每次我需要在派生类中使用其中一个基本属性(如 parentid)时,都会重复 json 名称。它会起作用,只是不是特别漂亮。我希望漂亮:D 我不得不为 NonDefaultingBoard 和其他所有衍生品重复它。

标签: c# json.net


【解决方案1】:

所以我想我解决了。我对 Ryan Wilson 的建议(在评论中)提出的问题是它会导致重复的代码。就像 JsonProperty(PropertyName = "keyname") 在几个不同的地方(在每个派生类中,我想使用具有不同属性的相同键)。我担心拼写错误或不一致迟早会潜入代码中并咬我。

我的解决方法是将键名存储在常量中:

public class BaseNode
{
    [JsonIgnore]
    public const string _constKeyName_sNodeParentId = "parentid";

    [JsonProperty(PropertyName = "id", Required = Required.DisallowNull)]
    public string _sNodeId { get; set; }

    [DisplayName("Parent Folder")]
    [DefaultValue("000000000000000000000000")]
    [MaxLength(24)]
    [MinLength(24)]
    public virtual string _sNodeParentId { get; set; }
}

然后重新使用属性中的常量作为键名,而不是按字面输入字符串:

public class NonDefaultingBoard : BaseBoardNode
{
    [JsonProperty(PropertyName = BaseNode._constKeyName_sNodeParentId, Required = Required.Always)]
    public override string _sNodeParentId { get => base._sNodeParentId; set => base._sNodeParentId = value; }

    [JsonProperty(PropertyName = BaseBoardNode._constKeyName_sNodeName, Required = Required.Always)]
    public override string _sNodeName { get => base._sNodeName; set => base._sNodeName = value; }

    [JsonProperty(PropertyName = BaseBoardNode._constKeyName_sNodeIP, Required = Required.Always)]
    public override string _sNodeIP { get => base._sNodeIP; set => base._sNodeIP = value; }

    [JsonProperty(PropertyName = BaseBoardNode._constKeyName_iNodePort, Required = Required.Always)]
    public override int _iNodePort { get => base._iNodePort; set => base._iNodePort = value; }
}

然后我可以在一个地方使用更改我的 parentid 键名,它会在整个代码中回响。以后也不会犯错。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多