【问题标题】:How to solve "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" Android error?如何解决“Newtonsoft.Json.JsonSerializationException 无法找到用于类型的构造函数”Android 错误?
【发布时间】:2020-01-15 18:32:44
【问题描述】:

我正在使用 Unity3D 开发应用程序。

我正在使用我自己的实用程序 DLL 和一些类。

我已经工作了几个月,并且毫无问题地进行了很多构建/编译。

上周向 DLL 添加了一个新类,它在我的 PC 上运行良好,但是当我构建项目并在我的 Android 设备中使用它时,它停止了工作。 Android Monitor 程序向我显示了该错误:

“Newtonsoft.Json.JsonSerializationException 无法找到用于类型的构造函数”

Newtonsoft 可以为其找到构造函数的类型,是我最近添加的新类。

重要提示:所有其他类都已反序列化,没有错误。

新类的唯一不同之处在于 namespacetype。变量、方法和构造函数还是一样的。

同样重要的是该项目在 PC 上可以正常运行,该问题仅在 Android 中出现。

我知道我可以为我的班级做一些自定义反序列化程序或添加标签等。但问题是只有那个类会导致问题,没有理由更改 JSon 反序列化系统。

谢谢。

【问题讨论】:

    标签: c# android unity3d dll json.net


    【解决方案1】:

    背景:这是源于 UnityLinker 的字节码剥离算法的常见问题。发生的事情是 UnityLinker 看不到您的类型构造函数的任何使用(因为 Newtonsoft.Json 仅通过反射使用它,编译器无法预见),因此将其删除。此字节码剥离仅在使用 IL2CPP 脚本后端构建时激活,这就是为什么您在 PC 上构建时没有遇到任何问题(或任何其他仅使用 Mono 的问题)。

    修复:要克服这个问题,您可以禁用该类型(甚至只是该构造函数)的字节码剥离。您可以使用link.xml 文件执行此操作。示例:

    <linker>
        <assembly fullname="MyAssembly">
            <type fullname="MyAssembly.MyCSharpClass">
                <!-- disables stripping just for the constructor -->
                <method signature="System.Void .ctor()"/>
            </type>
    
            <!-- disables stripping for the entire type -->
            <type fullname="MyAssembly.MyCSharpClass" preserve="all" />
        </assembly>
    </linker>
    

    我写了一些有用的页面,介绍使用 link.xml 以及其他工具来处理 AOT 问题,因为我发现 Unity 的文档缺乏且分散: https://github.com/jilleJr/Newtonsoft.Json-for-Unity/wiki/Fix-AOT-using-link.xml

    要详细了解为什么会这样,请参阅我的解释页面:https://github.com/jilleJr/Newtonsoft.Json-for-Unity/wiki/What-even-is-AOT

    【讨论】:

    • 正是我需要的!我的团队认为这个问题只发生在 IOS 中,但它是一个通用的 Newtonsoft 配置。
    • 谢谢@Applejag !!你救了我的一天!! ???
    【解决方案2】:

    正如其他人提到的那样,发生这种情况是因为 il2cpp 上的统一代码剥离有点过于急切,并且删除了构造函数,因为它看不到它真的被使用了。

    除了建议的解决方案之外,还可以将UnityEngine.Scripting.PreserveAttribute 添加到空构造函数中。像这样:

    using UnityEngine.Scripting;
    
    [Preserve] // Ensures it survives code-stripping
    public Response()
    {
    }
    

    我认为比使用 link.xml 更喜欢这种方式,因为它将与该类相关的所有内容保存在一个位置,而不是分布在多个文件中。

    【讨论】:

      【解决方案3】:
      1. 你可以在类中有一个空的构造函数来反序列化它。

      2. 你可以试着把它放在你的课堂上:

        [Runtime.Preserve(AllMembers = true)]

      【讨论】:

      • 但是我还是不知道问题的根源.. 1.我在任何类中都没有空的构造函数。 2. 我在任何地方都没有这样的标签.. 我应该把它放在那个有冲突的类中,而不知道真正的问题吗?
      【解决方案4】:

      Applejag 的答案是正确的(link.xml 或 AotHelper),但我有另一种选择。一个懒惰的。 :)

      在 Unity 的 iOS 和 Android 播放器设置中检查您的“托管剥离级别”。我的设置为高,当我切换到低时,它解决了问题。当然,这对文件大小有一些影响,但如果您在像我这样的小型应用程序中工作,那么这不是问题。

      【讨论】:

        猜你喜欢
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        • 2022-08-15
        • 2016-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多