{"id":22750094,"url":"https://github.com/pwall567/kjson-ktor","last_synced_at":"2026-04-28T17:02:37.768Z","repository":{"id":80627385,"uuid":"500739151","full_name":"pwall567/kjson-ktor","owner":"pwall567","description":"Reflection-based JSON serialization and deserialization for ktor","archived":false,"fork":false,"pushed_at":"2025-07-03T01:42:07.000Z","size":41,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-03T01:46:19.482Z","etag":null,"topics":["json","kotlin","ktor","ktor-client","ktor-server"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pwall567.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-06-07T07:42:18.000Z","updated_at":"2025-07-03T01:32:48.000Z","dependencies_parsed_at":"2025-06-21T21:46:02.294Z","dependency_job_id":null,"html_url":"https://github.com/pwall567/kjson-ktor","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/pwall567/kjson-ktor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Fkjson-ktor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Fkjson-ktor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Fkjson-ktor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Fkjson-ktor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pwall567","download_url":"https://codeload.github.com/pwall567/kjson-ktor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Fkjson-ktor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32390067,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","kotlin","ktor","ktor-client","ktor-server"],"created_at":"2024-12-11T04:12:21.052Z","updated_at":"2026-04-28T17:02:37.762Z","avatar_url":"https://github.com/pwall567.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kjson-ktor\n\n[![Build Status](https://github.com/pwall567/kjson-ktor/actions/workflows/build.yml/badge.svg)](https://github.com/pwall567/kjson-ktor/actions/workflows/build.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Kotlin](https://img.shields.io/static/v1?label=Kotlin\u0026message=v2.0.21\u0026color=7f52ff\u0026logo=kotlin\u0026logoColor=7f52ff)](https://github.com/JetBrains/kotlin/releases/tag/v2.0.21)\n[![Maven Central](https://img.shields.io/maven-central/v/io.kjson/kjson-ktor?label=Maven%20Central)](https://central.sonatype.com/artifact/io.kjson/kjson-ktor)\n\nThis library provides JSON serialization and deserialization for Ktor using the\n[`kjson`](https://github.com/pwall567/kjson) library.\nIn particular, it provides a streaming capability, so that items in a JSON array may be deserialised and processed as\nthey arrive, without waiting for the entire JSON document to be received.\n\n## Quick Start\n\nTo use `kjson-ktor`, in the `Application` module, specify:\n```kotlin\n    install(ContentNegotiation) {\n        kjson {\n            // specify JSONConfig configuration options here\n        }\n    }\n```\nThen, any responses from a REST call such as `call.respond(customerObject)` will use `kjson` serialisation.\n\nThe same configuration will cause POST or PUT data to be deserialised using `kjson`.\nFor example:\n```kotlin\n        val customerObject = call.receive\u003cCustomer\u003e()\n```\n\nClient REST calls may also make use of the same serialisation.\nIn the `HttpClient` configuration, specify:\n```kotlin\n    install(ContentNegotiation) {\n        kjson {\n            // specify JSONConfig configuration options here\n        }\n    }\n```\n(Observant readers will have noted that these lines are identical to those for server configuration.)\n\nClient calls will use `kjson` to serialise outgoing data and deserialise incoming client responses:\n```kotlin\n        val response = client.get(\"https://my.remote.server/customers/12345\")\n        val customer: Customer = response.body()\n```\nor:\n```kotlin\n        val response = client.put(\"https://my.remote.server/customers/12345\") {\n            setBody(customer)\n        }\n```\n\n## Streaming Output\n\nOutput from a Ktor REST call may be streamed automatically.\nIf the line:\n```kotlin\n        streamOutput = true\n```\nis added to the `JSONConfig` used by the application, output will be performed by an asynchronous process, serialising\nthe response object to JSON and outputting it on the fly.\nThis has significant benefits in both storage (no need to hold a long string of JSON in memory) and response time (the\nfirst bytes start appearing on the line much more quickly), but even greater benefits can be realised by the use of\n`Channel` or `Flow` collections.\n\nConsider the following example:\n```kotlin\n    routing {\n        get(\"/customers\") {\n            val flow = flow {\n                // a process to read the customer database and emit each object as it becomes available\n            }\n            call.respond(flow)\n        }\n    }\n```\n\nIn this case, the first bytes of the response may be sent **before the entire response list has been assembled**.\nA `Flow` will be serialised as a JSON array, and each object in the `Flow` collection will be serialised and sent in the\nresponse as it is added (by `emit()` to the `Flow`).\n\nThis asynchronous serialisation applies even if the `Flow` is a nested data property of a container object.\n\nAlternatively, a `Channel` may be used:\n```kotlin\n    routing {\n    get(\"/customers\") {\n        val channel = call.application.produce {\n            // a process to read the customer database and send each object as it becomes available\n        }\n        call.respond(channel)\n    }\n}\n```\n\nUsing this technique, completely asynchronous output can be achieved with very little effort.\n\n## Streaming Input\n\nIt's all very well for a REST service to send data asynchronously as it is produced, but that may not be particularly\nhelpful if the calling function is not able to process the objects as they arrive.\nIf the function simply accumulates the incoming JSON into a buffer and processes it only when the whole list has arrived\nlittle will have been gained.\n\nThe `kjson-ktor` library includes functions to read a client response, deserialise it on the fly and hand each item to\nthe calling function as it arrives.\n\nStreaming input is not quite as seamless as output; it requires a new function (an extension function on `HttpClient`).\nThe following:\n```kotlin\n        httpClient.receiveStreamJSON\u003cCustomer\u003e(\"$host/customers\") { customer -\u003e\n            // the code here is called with each Customer object as it is received\n        }\n```\nwill call the streaming output function from the previous section, with the `suspend` lambda being invoked with each\n`Customer` object in turn as it arrives.\n\nFor streaming input to work in this manner, the highest-level JSON element in the received data must be an array.\nAs each array item is completed it is deserialised using `kjson` and the resulting object is passed to the `suspend`\nlambda.\n\nThe full parameter list for the `receiveStreamJSON` function is (note that most parameters have appropriate defaults):\n\n| Name             | Type                  | Default                    | Notes                                                 |\n|------------------|-----------------------|----------------------------|-------------------------------------------------------|\n| `urlString`      | `String`              |                            | The target URL                                        |\n| `method`         | `HttpMethod`          | `HttpMethod.Get`           |                                                       |\n| `body`           | `Any`                 | `EmptyContent`             | The **request** body (Usually only for POST ot PUT)   |\n| `headers`        | `Headers`             | `Headers.Empty`            |                                                       |\n| `expectedStatus` | `HttpStatusCode`      | `HttpStatusCode.OK`        | (see [Exception Handling](#exception-handling) below) |\n| `config`         | `JSONConfig`          | `JSONConfig.defaultConfig` | The config to be used by `kjson` deserialisation      |\n| `consumer`       | `suspend (T) -\u003e Unit` |                            | Called with each array item                           |\n\nA second form is available with identical parameters except that the URL is specified as a `Url` rather than a `String`.\n\n**IMPORTANT:** Ktor does not allow access to the `JSONConfig` specified in the client configuration, so if `kjson`\nconfiguration options are required, the `JSONConfig` must be specified on `receiveStreamJSON()` call.\n\nIf a POST or PUT request body is provided, the function will add a `Content-Type: application/json` header, if no\n`Content-Type` header has been supplied using the `headers` parameter.\n\n### Exception Handling\n\nIf the response status code is not the one expected, a `JSONKtorClientException` will be thrown.\nThe exception will include information from the `HttpResponse` object, so that the full details of unexpected response\nmay be examined.\n\nThe properties of `JSONKtorClientException` are:\n\n| Name              | Type             |\n|-------------------|------------------|\n| `urlString`       | `String`         |\n| `statusCode`      | `HttpStatusCode` |\n| `responseHeaders` | `Headers`        |\n| `responseBody`    | `ByteArray?`     |\n| `config`          | `JSONConfig`     |\n\nThe `JSONKtorClientException` also has functions to allow access to the response body:\n- `bodyAsString()`: converts to `String` (using the character set in the response `Content-type` header if specified)\n- `body\u003cT\u003e()`: deserialises the body as a JSON object (also using the character set as above)\n\nFor example, if the called endpoint returns an `ErrorResponse` object in the case of errors:\n```kotlin\n        try {\n            httpClient.receiveStreamJSON\u003cCustomer\u003e(\"$host/customers\") { customer -\u003e\n                // process each customer\n            }\n        } catch (e: JSONKtorReceiveException) {\n            val errorResponse = e.body\u003cErrorResponse\u003e()\n            // make use of ErrorResponse object, for example log the content\n            // (note that errorResponse may be null if the response body was \"null\")\n        }\n```\nThe above is an over-simplified example; in the real world the code to deserialise the `ErrorResponse` object would most\nlikely be made conditional on the value of the status code (available at `e.statusCode`).\nIt would probably also be wrapped in its own `try ... catch` block.\n\n## JSON Lines\n\nThe [JSON Lines](https://jsonlines.org/) specification allows multiple JSON values to be specified in a single stream of\ndata, separated by newline (`\\u000a`) characters.\nFor example, events may be logged to a file as a sequence of objects on separate lines; the alternative would be to\noutput a JSON array, but this would require a \"`]`\" terminator, complicating the shutdown of the process (particularly\nabnormal shutdown).\n\n```json lines\n{\"time\":\"2023-06-24T12:24:10.321+10:00\",\"eventType\":\"ACCOUNT_OPEN\",\"accountNumber\": \"123456789\"}\n{\"time\":\"2023-06-24T12:24:10.321+10:00\",\"eventType\":\"DEPOSIT\",\"accountNumber\": \"123456789\",\"amount\":\"1000.00\"}\n```\n\n### Output JSON Lines\n\nThe JSON Lines format is particularly suitable for streaming data, and the `kjson-ktor` library includes functions to\noutput JSON Lines data from a `Channel` or a `Flow`:\n```kotlin\n        call.respondLines(channel)\n```\nor:\n```kotlin\n        call.respondLines(flow)\n```\n\n### Receiving JSON Lines\n\nThe `receiveStreamJSON` functions have equivalent functions named `receiveStreamJSONLines`; these functions operate in\nan identical manner to the original functions except that the input stream is expected to be in JSON Lines form.\n\n## Dependency Specification\n\nThe latest version of the library is 1.5, and it may be obtained from the Maven Central repository.\nThis version has been built using version 3.2.0 of Ktor.\n\n### Maven\n```xml\n    \u003cdependency\u003e\n      \u003cgroupId\u003eio.kjson\u003c/groupId\u003e\n      \u003cartifactId\u003ekjson-ktor\u003c/artifactId\u003e\n      \u003cversion\u003e1.5\u003c/version\u003e\n    \u003c/dependency\u003e\n```\n### Gradle\n```groovy\n    implementation 'io.kjson:kjson-ktor:1.5'\n```\n### Gradle (kts)\n```kotlin\n    implementation(\"io.kjson:kjson-ktor:1.5\")\n```\n\nPeter Wall\n\n2025-07-03\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwall567%2Fkjson-ktor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpwall567%2Fkjson-ktor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwall567%2Fkjson-ktor/lists"}