如何将子实例反序列化为父对象而不丢失其特定属性?

2024-04-02

下面分几个类。如何序列化 A 实例的 Json 字符串,其中 PropertyB 包含 SpecPropB1 或 SpecPropB2,以便这些属性保留在 C# 对象中?

public class A
{
  public B PropertyB {get;set;}
}

public class B
{
  public string GenProp {get;set;}
}

public class B1:B
{
  public string SpecPropB1 {get;set;}
}

public class B2:B
{
  public string SpecPropB2 {get;set;}
}

我看到了这个问题的多种解决方案,但它们缺乏优雅:

  • 将属性的类型作为对象:我失去了该属性的强类型。
  • 将有问题的部分重新序列化为子对象:这很快就会变得丑陋
  • 创建一个特定的类ASerialisable(具有B1和B2属性),将字符串序列化为此,然后使用构造函数从该类创建一个A对象:与上面相同,我担心如果有的话它会创建很多类类似的问题还有很多。 *在序列化之前添加对象的类型并使用属性TypeNameHandling。我没有看到一种不涉及部分反序列化的方法。

类似的问题,但我也不是序列化字符串的人,所以我无法使用此解决方案:反序列化为正确的子对象 https://stackoverflow.com/questions/22465868/deserialize-into-correct-child-objects

EDIT:

我创建了一个继承 JsonConverter 的新类,它自动完成 Falanwe 提出的工作。 这是最终的代码,供有需要的人使用。

private class BConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(A).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader,
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        if(objectType.IsSubclassOf(typeof(B)) || objectType == typeof(B))
        {
            if (item["SpecPropB1"] != null)
            {
                return new B1() 
                { 
                    GenProp = (string)item["GenProp"], 
                    SpecPropB1 = (string)item["SpecPropB1"] 
                };
            }
            else if (item["SpecPropB2"] != null)
            {
                return new B2()
                {
                    GenProp = (string)item["GenProp"],
                    SpecPropB2 = (string)item["SpecPropB2"]
                };
            }
            else
            {
                return new B()
                {
                    GenProp = (string)item["GenProp"]
                };
            }
        }
        else
        {
            return item.ToObject(objectType);
        }
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        //not implemented here but needed if you want to deserialized data,
        // this can help you: http://blog.maskalik.com/asp-net/json-net-implement-custom-serialization/
        throw new NotImplementedException();
    }
}

private class A
{

    public B PropertyB { get; set; }
}

[JsonConverter(typeof(BConverter))]
private class B
{
    public string GenProp { get; set; }
}

private class B1 : B
{
    public string SpecPropB1 { get; set; }
}

private class B2 : B
{
    public string SpecPropB2 { get; set; }
} 

如果这种情况仅在少数情况下出现,请序列化为具有这两个属性的 DTO(数据传输对象)类。如果您不想创建新的命名类,您还可以使用匿名类来为您完成这项工作

var myDto = JsonConvert.DeserializeAnonymousType(jsonString,
    new {
        PropertyB = new {
            GenProp ="",
            SpecPropB1 ="",
            SpecPropB2 = ""}
        });

如果这种情况出现得太频繁,也就是说,如果您不确定要反序列化的 json 的架构,则可以反序列化为 JObject,然后查询字段是否存在。

B b;
JObject o = JObject.Parse(jsonString);

// I need this variable to compile, but I won't use it.
JToken _;
if(o.TryGetValue("SpecPropB1", out _)
{
    b = o.ToObject<B1>();
}
else
{
//...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将子实例反序列化为父对象而不丢失其特定属性? 的相关文章

  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • 循环遍历 C 结构中的元素以提取单个元素的值和数据类型

    我有一个要求 我有一个 C 语言的大结构 由大约 30 多个不同数据类型的不同元素组成 typedef struct type1 element1 type2 element2 type3 element3 type2 element4 1
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • RestSharp获取序列化输出

    我正在寻找一种方法来访问 AddBody 调用的序列化结果 我正在使用内置的 RestSharp 序列化器 例子 class Foo public string FooField void SendRecord var f new Foo
  • 语音识别编程问题入门

    所以 你们可能都看过 钢铁侠 其中托尼与一个名为贾维斯的人工智能系统进行交互 演示剪辑here http www youtube com watch v Go8zsh1Ev6Y 抱歉 这是广告 我非常熟悉 C C 和 Visual Basi
  • 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?

    我注意到CallContext LogicalSetData LogicalGetData不按照我期望的方式工作 内部设置的值async方法得到恢复即使没有异步或任何类型的线程切换 无论如何 这是一个简单的例子 using System u
  • 后退按钮 (Chrome) 在 Play Framework 中获取 Json 而不是 HTML

    各位 我有一个 Web 应用程序 我在其中对同一资源的 JSON 和 HTML 表示重复使用了相同的路由 现在我们将其称为 foo details 该页面是从 bar details 链接的 因此 查看 bar details 您会看到链接
  • 已发布的 .Net Core 应用程序警告安装 .Net Core,但它已安装

    我制作了一个 WPF 和控制台应用程序 供某人在我无法访问的私人服务器上使用 我使用 Visual Studio 2019 的内置 发布向导 来创建依赖于框架的单文件应用程序 当该人打开 WPF 应用程序时 他们会看到标准警告 他们单击 是
  • 如何递归取消引用指针(C++03)?

    我正在尝试在 C 中递归地取消引用指针 如果传递一个对象 那就是not一个指针 这包括智能指针 我只想返回对象本身 如果可能的话通过引用返回 我有这个代码 template
  • 在 C 中使用枚举而不是 #defines 作为编译时常量是否合理?

    在 C 工作了一段时间后 我将回到 C 开发领域 我已经意识到 在不必要的时候应该避免使用宏 以便让编译器在编译时为您做更多的工作 因此 对于常量值 在 C 中我将使用静态 const 变量或 C 11 枚举类来实现良好的作用域 在 C 中
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • 将二变量 std::function 转换为单变量 std::function

    我有一个函数 它获取两个值 x 和 y 并返回结果 std function lt double double double gt mult double x double y return x y 现在我想得到一个常量 y 的单变量函数
  • 将 Word 转换为 PDF - 禁用“保存”对话框

    我有一个用 C 编写的 Word 到 PDF 转换器 除了一件事之外 它工作得很好 有时 在某些 Word 文件上 后台会出现一条消息保存源文件中的更改 gt 是 否 取消 但我没有对源文件进行任何更改 我只想从 Word 文件创建 PDF
  • 如何在 C# 中创建异步方法?

    我读过的每一篇博客文章都会告诉您如何在 C 中使用异步方法 但由于某些奇怪的原因 从未解释如何构建您自己的异步方法来使用 所以我现在有这段代码使用我的方法 private async void button1 Click object se
  • C++ 对象用 new 创建,用 free() 销毁;这有多糟糕?

    我正在修改一个相对较大的 C 程序 不幸的是 并不总是清楚我之前的人使用的是 C 还是 C 语法 这是在一所大学的电气工程系 我们 EE 总是想用 C 来做所有事情 不幸的是 在这种情况下 人们实际上可以逃脱惩罚 但是 如果有人创建一个对象
  • Visual Studio 2015:v120 与 v140?

    仅供参考 Win10 x64 我今天开始尝试 Visual Studio 2015 在弄清楚如何运行 C C 部分后 我尝试加载一个大型个人项目 该项目使用非官方的glsdk http glsdk sourceforge net docs
  • 无法将字符串文字分配给装箱的 std::string 向量

    这是我的类型系统的简化版本 include
  • 为什么空循环使用如此多的处理器时间?

    如果我的代码中有一个空的 while 循环 例如 while true 它将把处理器的使用率提高到大约 25 但是 如果我执行以下操作 while true Sleep 1 它只会使用大约1 那么这是为什么呢 更新 感谢所有精彩的回复 但我
  • 在 System.Type 上使用条件断点时出错

    这是函数 public void Init System Type Type this Type Type BuildFieldAttributes BuildDataColumns FieldAttributes 我在第一行设置了一个断点
  • 是否允许全局静态标识符以单个 _ 开头?

    换句话说 可能static 文件范围 全局变量恰好以一个下划线开头 而不会产生与 C 实现发生名称冲突的可能性 https www gnu org software libc manual html node Reserved Names

随机推荐