简体   繁体   English

在编译时从 JSON 生成 Swift+Java 设置对象

[英]Generate Swift+Java settings object from JSON at compile time

My mobile app has quite a lot of hard-coded data, that I want to share between the native Android and iOS versions of the app.我的移动应用程序有很多硬编码数据,我想在应用程序的原生 Android 和 iOS 版本之间共享。 I don't want to create two settings files for each app: I would like to have a single place where the information is stored.我不想为每个应用程序创建两个设置文件:我希望有一个存储信息的地方。

My first thought was using a JSON file embedded with my app and decode it at runtime.我的第一个想法是使用嵌入在我的应用程序中的 JSON 文件并在运行时对其进行解码。

Instead my goal here is to deserialize the app's data at compile time, in order to:相反,我的目标是在编译时反序列化应用程序的数据,以便:

  • track potential errors within the JSON file or the decoding code before shipping the app: the build will fail instead在发布应用程序之前跟踪 JSON 文件或解码代码中的潜在错误:构建将失败
  • avoid being slowed down by some deserialization at startup time避免在启动时被一些反序列化减慢
  • avoid leaving unencrypted app data lying around as JSON files (.ipa/.apk are zip files where resources can be easily extracted), I'd rather have it obfuscated in code避免将未加密的应用程序数据保留为 JSON 文件(.ipa/.apk 是可以轻松提取资源的 zip 文件),我宁愿在代码中对其进行混淆

I'm looking for a command line tool that I could add to my build scripts that given a JSON file infer a schema and thus classes AND instantiates an object with all the app settings.我正在寻找一个命令行工具,我可以将它添加到我的构建脚本中,该脚本给定一个 JSON 文件,从而推断出一个架构,从而推断出类并使用所有应用程序设置实例化一个对象。

For instance given the following settings.json file:例如给定以下 settings.json 文件:

{
    "gravity": 9.81,
    "scientists": ["Kepler", "Einstein", "Newton"],
    "planets": [
        {
            "name": "Mars",
            "radius": 3390
        },
        {
            "name": "Venus",
            "radius": 6052
        }
    ]
}

I would like to generate automatically a Settings.swift file that could look like:我想自动生成一个 Settings.swift 文件,它可能如下所示:

struct Settings {

    struct Planet {
        var name: String
        var radius: Int
    }

    var gravity: Double
    var scientists: [String]
    var planets: [Planet]

    static func content() -> Settings {
        return Settings(gravity: 9.81, scientists: ["Kepler", "Einstein", "Newton"], planets: [Planet(name: "Mars", radius: 3390), Planet(name: "Venus", radius: 6052)])
    }
}

I could then include the generated file into my project and call Settings.content() once, keep it in a global variable and use it throughout my project.然后我可以将生成的文件包含到我的项目中并调用 Settings.content() 一次,将它保存在一个全局变量中并在我的整个项目中使用它。

I want to achieve the same with Android as well.我也想在 Android 上实现同样的目标。

Tools like quicktype or json2swift do half the job and don't generate the object instantiation bit, that still needs to be done at runtime.像 quicktype 或 json2swift 这样的工具完成了一半的工作并且不生成对象实例化位,这仍然需要在运行时完成。

Any idea?任何的想法?

我创建了一个开源 NodeJS mobile_app_data工具来实现我想要的。

A possible solution will be as follows:可能的解决方案如下:

  1. Save the .json file in the project directory将 .json 文件保存在项目目录中
  2. In AppDelegate applicationDidFinishLauncing() read the above file into a Data object ( Read JSON file with Swift 3 )在 AppDelegate applicationDidFinishLauncing() 中将上述文件读入 Data 对象( 使用 Swift 3 读取 JSON 文件
  3. Make your Settings class implement Decodable (your inner class Planet will need to implement Decodable as well)使您的 Settings 类实现可解码(您的内部类 Planet 也需要实现可解码)
  4. Call JsonDecoder().decode() and provide the data you obtained in 2)调用 JsonDecoder().decode() 并提供您在 2) 中获得的数据
  5. You can then save this value anywhere you want然后您可以将此值保存在您想要的任何位置

I just noticed that you needed the generation to happed when Settings.content() is called.我刚刚注意到,当 Settings.content() 被调用时,你需要这一代发生。 Follow the above steps just move step 2) into the content() function按照上述步骤将步骤 2) 移到 content() 函数中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM