переход с Python JSON на Kotlin JVM JSON - PullRequest
0 голосов
/ 13 апреля 2019

У меня есть программы на 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 может получить доступ к документу выше 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.

1 Ответ

1 голос
/ 14 апреля 2019

Вы можете использовать Json.plain.parseJson(...) из среды сериализации Kotlins, чтобы получить нечто подобное.Он создаст дерево объектов 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)
}
...