1

I have existing Python programs which use import json and use

json.load()  json.loads()

method to read the json and present it in code in easy to use accessible dictionary.

I use python json[name][] = value constructs to reference the json data in memory and also use the same type of syntax to assign new values to json elements.

I want to migrate the Python code to Kotlin and looking for JSON libraries which will do something close to what Python json.load() does in Kotlin.

I did use Google but did not find anything, there are plenty of Kotlin/Java JSON libraries but I dont think they offer anything like Python JSON load methods.

What is my best option library to use?

Here are Python code details, I want to do same in Kotlin and use the existing JSON libraries.

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

Contents of js document is this:

{
    "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
}

here is how Python can access above json document using [] and range

    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"

I hope this clarifies what I am trying to do to migrate my Python code to Kotlin.

5
  • 2
    Maybe this is what you're looking for: stackoverflow.com/questions/44870961/… Commented Apr 13, 2019 at 7:34
  • 1
    If above link doesn't cover what you need, please state what load offers but you didn't find something similiar on kotlin. Commented Apr 13, 2019 at 15:32
  • 1
    you can use Gson library in kotlin Commented Apr 13, 2019 at 15:58
  • please see my original post - I edited the contents and provided sample python json code to see how I can do same in Kotlin using existing json libraries. Thank you. Commented Apr 13, 2019 at 23:33
  • You can use below online tool to convert json to kotlin workversatile.com/json-to-kotlin-converter Commented Aug 23, 2022 at 18:21

1 Answer 1

1

You can use Json.plain.parseJson(...) from Kotlins serialization framework to get something similar. It will create a tree of Json objects which then can be navigated like a map of maps.

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"
        }
    }

}

Make sure to include the Kotlin serialization plugin into your project setup. See the kotlinx.serialization Github project on how to do this.

As Kotlin is a statically typed language you should probably define a data class for your Json file and parse that file into an object of this data class instead of using the untyped approach above.

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)
}
Sign up to request clarification or add additional context in comments.

2 Comments

re this: val bodyData = Json.nonstrict.parse(BodyData.serializer(), data) - does not compile, serializer error: Unresolved reference: serializer. But if I use the generic like so: val r = Json.nonstrict.parse<RepartitionDataLakeConfigJson>(repartitionJsonConfig) // then it works. I am using latest Kotlin 1.3.31 and latest Json library as of March 2019. Thank you.
Unresolved reference: serializer works with Gradle. It's a known issue with IntelliJ (strangely). Json.nonstrict.parse<RepartitionDataLakeConfigJson>(repartitionJsonConfig) uses reflection in order to get the right serializer. This is fine for Java, but might be a problem in JS

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.