【问题标题】:migrating from Python JSON to Kotlin JVM JSON从 Python JSON 迁移到 Kotlin JVM JSON
【发布时间】:2019-04-13 07:04:12
【问题描述】:

我现有的 Python 程序使用 import json 并使用

json.load()  json.loads()

读取 json 并将其以代码形式呈现在易于使用的可访问字典中的方法。

我使用 python json[name][] = value 构造来引用内存中的 json 数据,并使用相同类型的语法为 json 元素分配新值。

我想将 Python 代码迁移到 Kotlin 并寻找 JSON 库,这些库的功能类似于 Python json.load() 在 Kotlin 中的功能。

我确实使用了 Google,但没有找到任何东西,有很多 Kotlin/Java JSON 库,但我认为它们没有提供类似 Python JSON 加载方法的东西。

什么是我最好的选择库?

这里是 Python 代码详细信息,我想在 Kotlin 中做同样的事情并使用现有的 JSON 库。

import json 
js = json.loads(response['Body'].read())

js文件的内容是这样的:

{
    "environment": "production",
    "postgres_host" : "pgstaging-prod.blah.blah.rds.amazonaws.com",
    "postgres_port" : 5432,
    "postgres_database" : "datawarehouse",
    "postgres_user" : "pguser",
    "postgres_password" : "!!!!!!",
    "postgres_config_schema" : "etl_operations",
    "postgres_validation_log_table_name" : "jobs_process_log",
    "postgres_destination_table_name" : "myleads",
    "debugFlag": true,
    "configBucket": "csn-datalake",
    "configFileName": "yurib_test/myleads.json",
    "HighWaterMarkFileName": "yurib_test/dts_high_watermark.json",
    "repartitionSourceTableName": "leads",
    "repartitionSourceDbName": "datalake",
    "sourceTablePartitionDateTime": "job_run_timestamp_utc",
    "repartitionTargetTableName": "outleads",
    "repartitionTargetDbName": "datalake_reports",
    "repartitionTargetS3Location": "yurib_test/outleads",
    "repartitionTargetColumnList": [
        {"colName": "message_item_countrycode", "isDatePartition": false, "renameTo" : "message_countrycode"},
        {"colName": "message_tenant_code", "isDatePartition": false, "renameTo" : "message_tenant"},
        {"colName": "message_lastupdated", "isDatePartition": true, "renameTo" : "message_lastupdated"}
        ],
    "repartitionLoadType": "incremental_data_load",
    "repartition": 4,
    "repartitionLoadTypeIncremental": "incremental_data_load",
    "repartitionLoadTypeFullInitial": "full_data_load",
    "countryCodeColName": "message_item_countrycode",
    "tenantColName": "message_tenant_code",
    "autoCreateCountryTenant": false,
    "autoCreateCountry": true,
    "autoCreateTenant": true,
    "partitionDateDefault": "0000-00-00",
    "partitionYearDefault": "0000",
    "partitionMonthDefault": "00",
    "partitionDayDefault": "00",
    "countryCodeDefault": "AU",
    "tenantDefault": "CARSALES",
    "missingPartColDataValReplace": "MISSINGDATA",
    "validateIncomingCountryTenant": true,
    "datePartitionStyle": "ym",
    "datePartitionStyleYearMonth": "ym",
    "datePartitionStyleYearMonthDay": "ymd",
    "propagateGlueJobRunGuid": false
}

这里是 Python 如何使用 [] 和 range 访问上述 json 文档

    print (js["repartitionLoadType"])
    print (js['configBucket'], js['configFileName'], js['HighWaterMarkFileName'])
    print (js['repartitionTargetTableName'], js['repartitionTargetS3Location'])
    print (js['repartitionSourceTableName'], js['repartitionSourceDbName'])
    print (js['repartitionTargetDbName'], js['repartitionLoadType'])
    print (js['autoCreateCountry'], js['autoCreateTenant'], js['missingPartColDataValReplace'])
    print (js['countryCodeColName'], js['tenantColName'], js['propagateGlueJobRunGuid'])
    print (js['countryCodeDefault'], js['tenantDefault'], js['validateIncomingCountryTenant'], js['repartition'])

    partition_dts = ""
    # json array
    for i in range(0, len(js['repartitionTargetColumnList'])):
        if True == js['repartitionTargetColumnList'][i]['isDatePartition']:
            partition_dts = "`" + js['repartitionTargetColumnList'][i]['colName'] + "`"
        else:
            js['repartitionTargetColumnList'][i]['colName'] = "new value replace/assign here"
        continue

# to set/replace/assign any values above:
    js["repartitionLoadType"] = "some new value"

我希望这能阐明我正在尝试将我的 Python 代码迁移到 Kotlin 的操作。

【问题讨论】:

  • 也许这就是你要找的东西:stackoverflow.com/questions/44870961/…
  • 如果上面的链接不能满足您的需求,请说明load 提供的内容,但您没有在 kotlin 上找到类似的内容。
  • 你可以在 kotlin 中使用 Gson 库
  • 请查看我的原始帖子 - 我编辑了内容并提供了示例 python json 代码,以了解如何使用现有的 json 库在 Kotlin 中做同样的事情。谢谢。

标签: python json kotlin kotlinx.serialization


【解决方案1】:

您可以使用 Kotlins 序列化框架中的 Json.plain.parseJson(...) 来获得类似的东西。它将创建一个 Json 对象树,然后可以像地图一样导航。

import kotlinx.serialization.json.Json
import kotlinx.serialization.json.content
import java.lang.StringBuilder

fun main() {

    val js = Json.plain.parseJson(data).jsonObject

    println(js["repartitionLoadType"]?.content)
    // ...

    var partitionDts = StringBuilder()

    for (repartitionTargetColumn in js["repartitionTargetColumnList"]!!.jsonArray) {
        if (repartitionTargetColumn.jsonObject["isDatePartition"]?.primitive?.boolean!!) {
            partitionDts.append("`" + repartitionTargetColumn.jsonObject["colName"] + "`");
        }
        else {
            // JsonObjects are immutable in Kotlin
            // repartitionTargetColumn.jsonObject["colName"] = "new value replace/assign here"
        }
    }

}

确保将 Kotlin 序列化插件包含在您的项目设置中。请参阅kotlinx.serialization Github 项目了解如何执行此操作。

由于 Kotlin 是一种静态类型语言,您可能应该为您的 Json 文件定义一个数据类并将该文件解析为该数据类的对象,而不是使用上面的无类型方法。

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

@Serializable
data class BodyData(
    var environment: String,
    var repartitionLoadType: String
    // ...
)

fun main() {
    val bodyData = Json.nonstrict.parse(BodyData.serializer(), data)
    println(bodyData.repartitionLoadType)
}

【讨论】:

  • re this: val bodyData = Json.nonstrict.parse(BodyData.serializer(), data) - 无法编译,序列化程序错误:未解析的引用:序​​列化程序。但是,如果我像这样使用泛型: val r = Json.nonstrict.parse(repartitionJsonConfig) // 那么它可以工作。截至 2019 年 3 月,我正在使用最新的 Kotlin 1.3.31 和最新的 Json 库。谢谢。
  • Unresolved reference: serializer 与 Gradle 一起使用。这是 IntelliJ 的一个已知问题(奇怪)。 Json.nonstrict.parse<RepartitionDataLakeConfigJson>(repartitionJsonConfig) 使用反射来获得正确的序列化程序。这对 Java 来说很好,但在 JS 中可能是个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-25
  • 2023-02-19
  • 2019-11-28
  • 1970-01-01
  • 1970-01-01
  • 2015-11-09
  • 1970-01-01
相关资源
最近更新 更多