-
Notifications
You must be signed in to change notification settings - Fork 2
[Question] How do I modify json continuously? #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Maybe I can try this? And recently I want to learn how to use Arrow, Please give me some advice! val result = data.run {
JsonPath.path("sd.n").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.ensureAscii().escaped().addQuotes())
}.run {
JsonPath.path("sd.lmz").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString())
}
}.run {
JsonPath.path("sd.rsd.wr").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString())
}
}.run {
JsonPath.path("sd.rsd.lr").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString())
}
}
}
or val result = data
.apply {
JsonPath.path("sd.n").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.ensureAscii().escaped().addQuotes())
}
}
.apply {
JsonPath.path("sd.lmz").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString())
}
}
.apply {
JsonPath.path("sd.rsd.wr").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString())
}
}
.apply {
JsonPath.path("sd.rsd.lr").modify(this) {
JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString())
}
}
println(Json.encodeToString(result) == origin) // true But it still feels quite troublesome lol... |
Sorry for the late reply. Have you tried using the val result = data.copy {
JsonPath.path("sd.n").transform { JsonUnquotedLiteral(it.jsonPrimitive.content.ensureAscii().escaped().addQuotes()) }
JsonPath.path("sd.lmz").transform { JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString()) }
JsonPath.path("sd.rsd.wr").transform { JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString()) }
JsonPath.path("sd.rsd.lr").transform { JsonUnquotedLiteral(it.jsonPrimitive.content.toBigDecimal().setScale(6).toString()) }
} |
Thanks for your reply, I've written these for a new DSL. Hope you enjoy it! /**
* Converts the current [JsonElement] into a [JsonUnquotedLiteral] decimal string with the specified precision.
*
* @param scale Number of decimal places to retain, defaults to 6.
* @return A [JsonPrimitive] representing the unquoted JSON string.
*
* Example: `"3.1415926535"` -> `3.141593`
*/
fun JsonElement.toScaledLiteral(scale: Int = 6): JsonPrimitive =
JsonUnquotedLiteral(this.jsonPrimitive.content.toBigDecimal().setScale(scale).toString())
/**
* Wraps the current string with double quotes (`"`).
*/
private fun String.addQuotes(): String = "\"$this\""
/**
* Encodes each character in the current string as `\\uXXXX`, ensuring it is ASCII-safe.
*/
private fun String.ensureAscii(): String = this.toCharArray().joinToString("") {
"\\u" + it.code.toString(16).padStart(4, '0')
}
/**
* Converts the current [JsonElement] into a fully ASCII-safe [JsonUnquotedLiteral] string and wraps it in quotes.
*
* Typically used for safely displaying or transmitting JSON field values over the network.
*/
fun JsonElement.toAsciiLiteral(): JsonPrimitive =
JsonUnquotedLiteral(this.jsonPrimitive.content.ensureAscii().escaped().addQuotes())
/**
* Modifies values at specified paths within the current [JsonElement] using a DSL-style block.
*
* Example:
* ```kotlin
* val modified = json.modify {
* path("a.b") { it.toScaledLiteral() }
* path("x.y") { it.toAsciiLiteral() }
* }
* ```
*
* @param block A configuration block that defines the paths and transformation logic.
* @return A new [JsonElement] with the specified modifications applied.
*/
inline fun JsonElement.modify(block: JsonCopyBuilder.() -> Unit): JsonElement {
val builder = JsonCopyBuilder(this)
builder.block()
return builder.build()
}
/**
* A builder class for composing multiple JSON path-based transformations.
*
* @property original The initial [JsonElement] to transform.
*/
class JsonCopyBuilder(original: JsonElement) {
private var current = original
/**
* Applies a transformation function to the value at the specified JSON [path].
*
* @param path A JSON path string (e.g., `"a.b[0].c"`).
* @param transformer A function to transform the [JsonElement] located at the path.
*/
fun path(path: String, transformer: (JsonElement) -> JsonElement) {
current = JsonPath.path(path).modify(current, transformer)
}
/**
* Returns the final [JsonElement] after all transformations have been applied.
*/
fun build(): JsonElement = current
} and use it for this: val result = data.modify { // data must be a jsonElement
path("sd.n") { it.toAsciiLiteral() }
path("sd.lmz") { it.toScaledLiteral() }
path("sd.rsd.wr") { it.toScaledLiteral() }
path("sd.rsd.lr") { it.toScaledLiteral() }
} If you see this reply, you could close this issue. I have no permission. |
Oh, I really do like your builder... Curious if we can enable it within the fun Copy.path(path: String, transformer: (JsonElement) -> JsonElement) {
JsonPath.path(path).transform(transformer)
} |
Yeah, you're right, but Copy needs a recevier, so you need write it such like: fun Copy<JsonElement>.path(path: String, transformer: (JsonElement) -> JsonElement) {
JsonPath.path(path).transform(transformer)
} then can use like: val result = data.copy { // data must be a jsonElement
path("sd.n") { it.toAsciiLiteral() }
path("sd.lmz") { it.toScaledLiteral() }
path("sd.rsd.wr") { it.toScaledLiteral() }
path("sd.rsd.lr") { it.toScaledLiteral() }
} JsonObject is needed, but I think JsonElement is all right. |
I use this to modify my json, but I have a problem. I had never known Arrow before, how do I modify my json without declare so many variables?
Here is the issue I sended before. I don't want to declare so many variables, nor do I want to use let for multi-layer nesting. Is parZip works better? Please give me some choice.
The text was updated successfully, but these errors were encountered: