【问题标题】:Proper way for child-classes to have common properties with different types子类具有不同类型的共同属性的正确方法
【发布时间】:2018-10-29 21:42:40
【问题描述】:

我有一个 JSON 对象,它将被格式化为:

{
"myNodes": [
    {
        "param1": 1,
        "param2": "myValue2a",
        "param3": {
            "myParam3param": 0
        }
    },
    {
        "param1": 1,
        "param2": "myValue2b",
        "param3": [
        {
            "myItemA": "abc",
            "myItemB": "def",
            "myItemC": "0"
        }]
    },
    {
        "param1": 1,
        "param2": "myValue2c",
        "param3": [
        {
            "myItemA": "ghi",
            "myItemB": "jkl",
            "myItemC": "0"
        }]
    }]
}

在 C# 中,我想知道如何构造响应对象来处理这个问题。我猜我会有某种包含 param1、param2 和 param3 的父类或接口。但是,param3 需要声明为“对象”类型,有时它是一个带有 myParam3param 的对象,有时它是一个事物列表。我也猜测我应该使用子类来确定 param3 是什么类型。

这可能吗?这应该如何实现……抽象类或接口?

【问题讨论】:

  • 如果数据类型和属性数量不同,那么您可能有 2 个不同的类。
  • 但我想说 myNodes 是一个 parentClass 类型的列表(不管它可能是什么......肯定有 param1、param2 和 param3)。
  • 你能接受最后两个参数的值为空吗?如果是这样,那么您只能上 1 节课。
  • Json.Net 的 JObject 实现了 IDictionary。您可以使用键/值(可以是另一个对象)向其中添加任何内容,因此您不必使用严格的模型。

标签: c# json interface abstract-class


【解决方案1】:
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public partial class ChildClasses
{
    [JsonProperty("myNodes")]
    public List<MyNode> MyNodes { get; set; }
}

public partial class MyNode
{
    [JsonProperty("param1")]
    public long Param1 { get; set; }

    [JsonProperty("param2")]
    public string Param2 { get; set; }

    [JsonProperty("param3")]
    public Param3Union Param3 { get; set; }
}

public partial class Param3Element
{
    [JsonProperty("myItemA")]
    public string MyItemA { get; set; }

    [JsonProperty("myItemB")]
    public string MyItemB { get; set; }

    [JsonProperty("myItemC")]
    public string MyItemC { get; set; }
}

public partial class PurpleParam3
{
    [JsonProperty("myParam3param")]
    public long MyParam3Param { get; set; }
}

public partial struct Param3Union
{
    public List<Param3Element> Param3ElementArray;
    public PurpleParam3 PurpleParam3;

    public bool IsNull => Param3ElementArray == null && PurpleParam3 == null;
}

public partial class ChildClasses
{
    public static ChildClasses FromJson(string json) => JsonConvert.DeserializeObject<ChildClasses>(json, QuickType.Converter.Settings);
}

public static class Serialize
{
    public static string ToJson(this ChildClasses self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}

internal static class Converter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
        Converters = {
            new Param3UnionConverter(),
            new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
        },
    };
}

internal class Param3UnionConverter : JsonConverter
{
    public override bool CanConvert(Type t) => t == typeof(Param3Union) || t == typeof(Param3Union?);

    public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null) return null;
        switch (reader.TokenType)
        {
            case JsonToken.StartObject:
                var objectValue = serializer.Deserialize<PurpleParam3>(reader);
                return new Param3Union { PurpleParam3 = objectValue };
            case JsonToken.StartArray:
                var arrayValue = serializer.Deserialize<List<Param3Element>>(reader);
                return new Param3Union { Param3ElementArray = arrayValue };
        }
        throw new Exception("Cannot unmarshal type Param3Union");
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        var value = (Param3Union)untypedValue;
        if (value.Param3ElementArray != null)
        {
            serializer.Serialize(writer, value.Param3ElementArray); return;
        }
        if (value.PurpleParam3 != null)
        {
            serializer.Serialize(writer, value.PurpleParam3); return;
        }
        throw new Exception("Cannot marshal type Param3Union");
    }
}`

【讨论】:

  • 来自 json 示例 param3 具有属性 myParam3param
猜你喜欢
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 2023-01-05
  • 2021-07-24
  • 2018-12-31
  • 1970-01-01
相关资源
最近更新 更多