Json.net 上的反序列化更改属性类型和名称

2024-02-27

使用 json.net,当我反序列化 json 字符串时,我需要将 json 列表映射到另一个字段并转换类型。

为了清楚起见,我有这个类(它是生成的代码,我无法更改它):

[Serializable]
public partial class Nbgv
{
    public virtual IReadOnlyList<string> BuildMetadataWithCommitId => BuildMetadataWithCommitIdInternal.AsReadOnly();
    internal List<string> BuildMetadataWithCommitIdInternal { get; set; } = new List<string>();
}

我有这个 json 字符串:

string json = @"{
    ""BuildMetadataWithCommitId"": [
        ""c390a213b7""
    ]
}";

如你看到的BuildMetadataWithCommitId依赖于取决于BuildMetadataWithCommitIdInternal.

我使用自定义解析器尝试了几件事,但没有任何效果。我没有找到如何告诉 json.net 如果您找到一个通用列表的属性,请将其映射到以 *Internal 结尾的字段。

private class CustomContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        property.Writable = true;
        if (IsList(property.PropertyType))
        {
            property.PropertyName += "Internal";
            property.PropertyType = ToList(property.PropertyType);
        }

        return property;
    }

    private Type ToList(Type t)
    {
        var genericListType = typeof(List<>);
        var specificListType = genericListType.MakeGenericType(t.GenericTypeArguments[0]);
        return specificListType;
    }

    private bool IsList(Type t)
    {
        if (t == null) return false;

        var res = t.IsGenericType &&
                   t.GetGenericTypeDefinition().IsAssignableFrom(typeof(IReadOnlyList<>));

        return res;
    }
}

你的基本问题是你的CustomContractResolver仅改变PropertyName https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_PropertyName.htm and PropertyType https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_PropertyType.htm归来的JsonProperty https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_JsonProperty.htm,然而底层的PropertyInfo https://learn.microsoft.com/en-us/dotnet/api/system.reflection.propertyinfo?view=netframework-4.8它的创造来源仍然是公共替代财产,而不是私人内部“真实”财产。就这样ValueProvider https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_ValueProvider.htm,除其他外,仍然是错误的。

你需要做的是生成一个JsonProperty对于内部属性,更正其名称和可访问性,然后返回代替 the JsonProperty为了公共财产。这将确保序列化程序将序列化和反序列化内部属性而不是其公共代理。

以下合同解析器完成这项工作:

public class CustomContractResolver : DefaultContractResolver
{
    const string InternalSuffix = "Internal";

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = member as PropertyInfo;
        var jProperty = base.CreateProperty(member, memberSerialization);
        if (property != null && jProperty != null && memberSerialization != MemberSerialization.Fields && !jProperty.HasMemberAttribute)
        {
            var replacementName = jProperty.UnderlyingName + InternalSuffix;

            // Check for replacement property.
            var replacementProperty = jProperty.DeclaringType.GetProperty(replacementName, BindingFlags.Instance | BindingFlags.NonPublic);
            if (replacementProperty != null
                && replacementProperty.GetGetMethod(true) != null && replacementProperty.GetSetMethod(true) != null
                && ReplacementTypeCompatible(property, replacementProperty.PropertyType)
                )
            {
                var replacementJProperty = base.CreateProperty(replacementProperty, memberSerialization);
                replacementJProperty.PropertyName = jProperty.PropertyName;
                if (!replacementJProperty.Readable && replacementProperty.GetGetMethod(true) != null)
                    replacementJProperty.Readable = true;
                if (!replacementJProperty.Writable && replacementProperty.GetSetMethod(true) != null)
                    replacementJProperty.Writable = true;
                return replacementJProperty;
            }

            // Check for replacement field.
            var replacementField = jProperty.DeclaringType.GetField(replacementName, BindingFlags.Instance | BindingFlags.NonPublic);
            if (replacementField != null
                && ReplacementTypeCompatible(property, replacementField.FieldType)
                )
            {
                var replacementJProperty = base.CreateProperty(replacementField, memberSerialization);
                replacementJProperty.PropertyName = jProperty.PropertyName;
                replacementJProperty.Readable = true;
                replacementJProperty.Writable = true;
                return replacementJProperty;
            }
        }

        return jProperty;
    }

    static bool ReplacementTypeCompatible(PropertyInfo property, Type replacementType)
    {
        // Add here whatever restrictions you need
        if (property.PropertyType.IsGenericType && typeof(IReadOnlyList<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition())
            && replacementType.IsGenericType && typeof(List<>).IsAssignableFrom(replacementType.GetGenericTypeDefinition())
            && replacementType.GetGenericArguments().SequenceEqual(property.PropertyType.GetGenericArguments()))
            return true;
        return false;
    }
}

要使用它,请将解析器的实例缓存在某处表现 https://www.newtonsoft.com/json/help/html/Performance.htm#ReuseContractResolver:

static IContractResolver customContractResolver = new CustomContractResolver();

并像这样反序列化:

var settings = new JsonSerializerSettings
{
    ContractResolver = customContractResolver,
};
var root = JsonConvert.DeserializeObject<Nbgv>(json, settings);

Notes:

  • 在你的问题中,你说我需要将 json 列表映射到另一个field

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Json.net 上的反序列化更改属性类型和名称 的相关文章

  • C - 计算文件中的单词、字符和行数。字符数

    我必须用 C 编写一段代码 输出给定文件中的字符数 行数和单词数 任务看起来很简单 但我现在真的不确定出了什么问题 所以 这是代码 include
  • 命名管道客户端无法连接到作为网络服务运行的服务器

    我有一个服务在网络服务帐户下运行 该服务只是设置一个命名管道并侦听连接 NamedPipeServerStream listeningPipe new NamedPipeServerStream ourservicepipe PipeDir
  • 表达式访问者仅为某些 lambda 表达式调用 VisitParameter

    我希望能够使用嵌套扩展方法将 EF 中的实体投影到相应的视图模型 参见我之前的问题使用扩展方法在 EF 中投影单个实体 https stackoverflow com questions 39585427 projection of sin
  • 等待运算符错误

    我的代码有问题 我怎么解决这个问题 这个问题出现在await操作符中 public MyModel HttpClient client new HttpClient HttpResponseMessage response await cl
  • 提取单花括号内的值

    我想要一个收藏 value 一个字符串使用正则表达式 例如 lorem ipsum field1 lorem ipsum field2 lorem ipsum field1 lorem ipsum field2 field3 我会得到 fi
  • 为什么 fgets 接受 int 而不是 size_t?

    功能如strcpy malloc strlen 和其他各种接受他们的参数或返回值作为size t代替int or an unsigned int出于显而易见的原因 一些文件功能 例如fread and fwrite use size t以及
  • 带有嵌入 Flash 视频的 PDF 示例?

    有谁知道我在哪里可以查看嵌入 Flash 视频的 PDF 示例 我知道问这个问题很愚蠢 因为你会认为任何面向技术的用户都应该能够使用谷歌找到一个 但我真的找不到 我的另一个问题是 使用 C 中的 API 将 Flash 视频嵌入 PDF 文
  • 为什么 ObservableCollection 有两个集合构造函数?

    The 可观察集合 T https msdn microsoft com en us library ms668604类有两个构造函数 可以在其中传递项目集合 一个构造函数接受一个IEnumerable T 另一个List T 鉴于List
  • UI 线程正在阻塞调用 COM 对象的后台线程

    我正在开发一个通过第三方 COM 库与外部设备通信的应用程序 我试图让与设备的所有通信都通过后台线程 以防止通信问题搞砸我的应用程序 并消除在 UI 线程中进行通信所引入的一些其他复杂性 问题是 每当发生导致主 UI 线程阻塞的情况 即调用
  • 如何在Unity Inspector中创建多维数组?

    如何在 Unity Inspector 中创建枚举多维数组并使其可序列化 以便我可以从不同的脚本调用它 public enum colors red blue green yellow cyan white purple public in
  • 为什么我收到编译错误“使用已删除的函数 'std::unique_ptr ...”

    我收到一条巨大的编译错误消息 c mingw include c 6 1 0 bits predefined ops h 123 18 error use of deleted function std unique ptr lt Tp D
  • 将 std::pair const 转换为 std::pair const 安全吗?

    理论上或实践上 安全吗reinterpret cast a std pair
  • 将旧的 Unity 代码升级到 Unity 5

    在触发按钮上播放动画的代码似乎不起作用 我在 Youtube 上看到了一个视频 内容很简单animation Play 它可以在该视频上运行 但我无法让它在我的计算机上运行 我做错了什么还是团结改变了它 请帮助我在网上找不到解决方案 所有
  • 如何将 Boost Spirit 自动规则与 AST 结合使用?

    编辑 当我想在另一个规则上使用它时 我扩展了 sehe 的示例以显示问题 http liveworkspace org code 22lxL7 http liveworkspace org code 22lxL7 17 我正在尝试提高 Bo
  • 快速将文本附加到文本框

    我有一个BackgroundWorker正在发布消息的线程 使用BeginInvoke在 GUI 中的文本框中 方法 write debug text 在文本框中显示文本使用AppendText并将文本写入Console 外观上是这样的Ba
  • C中使用JNI从对象获取对象

    public class Student private People people private Result result private int amount 这是 Java 中类的示例 在C中 我试图获取 学生 中的 人 但失败了
  • 调用泛型类的方法

    这是上下文 我尝试编写一个映射器来动态地将域模型对象转换为 ViewModel 对象 我遇到的问题是 当我尝试通过反射调用泛型类的方法时 出现此错误 System InvalidOperationException 无法对 Contains
  • 从数据库配置中的连接字符串中删除 SSIS 密码

    我有一个 SSIS 包 它使用 SQL 服务器中的 SSIS 配置表来检索 OLE DB 连接管理器的连接字符串属性 问题是我还需要相同的连接字符串来调用使用实体框架的程序集 我尝试访问连接管理器连接字符串属性 但 SSIS 总是删除密码
  • Selenium - 模式对话框存在 - 如何接受信息?

    我有以下问题 在页面上提交一些日期后 我有一个如图所示的模式对话框 我想单击 ENTER 来浏览该模式 但它不起作用 我有以下代码 driver FindElement By CssSelector input submit Click A
  • 如何使用实体框架设置连接字符串

    我将 EF6 与 MySQL 结合使用 并有一个用于多个数据库的模型 我希望能够在我的表单中设置连接设置 如何以编程方式设置模型的连接字符串 你应该使用EntityConnectionFactory这就是您所需要的 public strin

随机推荐

  • Android Spinner:获取所选项目更改事件

    当所选项目发生更改时 如何设置 Spinner 的事件侦听器 基本上我想做的事情与此类似 spinner1 onSelectionChange handleSelectionChange void handleSelectionChange
  • 如何在 Ubuntu 上的 NetBeans 中设置 zend 自动完成

    我在 Ubuntu 11 04 上的 NetBeans 7 1 中设置 Zend 自动完成代码时陷入困境 一点帮助就太好了 我在工具 gt 选项 gt PHP gt Zend中设置 usr bin zf sh 作为 Zend 脚本 按下 注
  • 返回引用与返回值 C++ 之间的区别

    关于为什么有必要从函数返回引用的问题 如果我们替换以下代码 其行为完全相同int with int在第 9 行和第 16 行 在我的示例代码中 返回引用与值并不重要吗 在什么样的例子中它会开始变得重要 在我看来 我们无法返回函数局部变量的引
  • 禁用 iframe 自动调整大小

    我正在使用一个包含 iframe 的网页 iframe 中包含大量数据 每次加载时 其高度都会扩展到其中内容的范围 然而 这使我的页面消失了 是否有办法锁定 iframe 的高度并允许用户滚动浏览内容 嗯 奇怪 你有这个问题的示例链接吗 当
  • 在 OS X 上的 Java swing 中设置默认应用程序图标图像

    我正在尝试设置 Jar 文件的图标图像 setIconImage new ImageIcon getClass getResource logo png getImage 在 Mac OS X 10 7 4 中运行时 出现以下错误 Jun
  • Jenkins 管道:如何触发另一个作业并等待它而不使用额外的代理/执行器

    我正在尝试设置各种 Jenkins 管道 其最后阶段始终是运行一些验收测试 长话短说 所有产品的验收测试和测试数据 其中大部分是共享的 都被签入同一个存储库 大小约为 0 5 GB 因此 似乎最好为验收测试提供一个单独的工作 并通过每个管道
  • 铁路路线:具有约束的控制器命名空间(子域)

    目的是创建一个子域来容纳所有管理功能 CRUD 子域的名称是 admin 负责的控制器集也组织在 的命名空间下admin 即控制器位于应用程序 控制器 管理目录 理想情况下 应该有以下路线 admin mydomain com produc
  • 如何在文本视图的左上角设置可绘制对象?

  • 对数据表中的筛选列求和

    我正在尝试对数据表中过滤列的结果求和 我查看了他们网站上提出的问题 人们已经成功使用这个方法 http datatables net forums discussion 2053 fnfootercallback sum column af
  • 如何比较 string.characterAtIndex 和字母?

    我使用 swift 我想做的是检查这一点 if string characterAtIndex i a 但我收到错误 如何转换这个 a 以便它可以与我循环的字符类型相同 Thanks 你需要转变你UniChar characterAtInd
  • PhoneGap/Cordova 以及最新版本的 Google Chrome 中没有“Access-Control-Allow-Origin”

    我工作于Sencha Touch Framework跨移动平台 我正在运行我的项目mac os x localhost 我试图通过请求获取服务器的响应Ext Ajax request 我收到一个典型错误CORS XMLHttpRequest
  • 在 C/C++ 中初始化大小未知的数组 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何在 C 中初始化数组 例如 void initArr int size C语言没有提供初始化数组的选项 如果他的大小不是一个常量值 并
  • 如何判断CSS是否已经加载?

    我如何断言页面的 CSS 已在 Watin 2 1 中成功加载并应用其样式 在做了一些研究并写下我的答案之后 我偶然发现这个链接 http www phpied com when is a stylesheet really loaded
  • iOS 5 中的离屏 UITextView 不可见/清晰文本

    我有一个从笔尖加载的离屏 UITextView 实例 当用户点击 评论 按钮时 该实例会移动到屏幕框架中 输入使用的任何文本都是不可见的 如果用户旋转设备 则会显示文本 我尝试过抛出 setNeedsDisplay 和 setNeedsLa
  • ffmpeg的UDP协议是什么?

    ffmpeg的UDP协议是什么 这是另一个例子question https stackoverflow com questions 12003014 pipe udp input to ffmpeg ffmpeg i udp localho
  • 我们可以检查一个指针以确保它是一个有效的地址吗?

    我的想法是打印它指向的对象 我认为一个有效的指针应该有一个有效的对象 如果我们尝试打印出对象 我们会验证指针是否有效 我对吗 我认为一个有效的指针应该有一个有效的对象 是的 这就是有效指针的定义 如果我们尝试打印出对象 我们会验证指针是否有
  • setInterval 不适用于 ajax 调用

    我对网络服务进行了 getJson 调用并且工作正常 现在我尝试每 10 秒发出一次请求 使用带有回调函数的 setInterval 来触发弹出警报 我无法让它发挥作用 这是代码 function ajxCall getJSON http
  • 如何停止和播放jquery脚本

    我在用着slidesjs http www slidesjs com 在单页网站上创建 5 个不同的幻灯片 画廊 它们都有 slides 类并有自己的 ID 在调用播放函数之前 我不希望播放任何幻灯片 我已经能够使用以下方法成功阻止每个幻灯
  • 何时方便使用 Executors.newSingleThreadExecutor() 的示例

    请有人告诉我一个现实生活中的例子 在哪里使用这个工厂方法比其他方法更方便 新的单线程执行器 公共静态 ExecutorService newSingleThreadExecutor 创建一个执行器 它使用单个工作线程来操作 无界队列 但请注
  • Json.net 上的反序列化更改属性类型和名称

    使用 json net 当我反序列化 json 字符串时 我需要将 json 列表映射到另一个字段并转换类型 为了清楚起见 我有这个类 它是生成的代码 我无法更改它 Serializable public partial class Nbg