initial commit

This commit is contained in:
2025-07-31 14:54:21 +08:00
commit 4c97d691fc
17 changed files with 836 additions and 0 deletions

101
core/build.gradle.kts Normal file
View File

@@ -0,0 +1,101 @@
import java.util.*
plugins {
alias(libs.plugins.dokka)
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.maven.publish)
}
repositories {
mavenCentral()
}
dependencies {
implementation(libs.kotlinx.coroutines)
implementation(libs.kotlinx.datetime)
implementation(libs.ktor.serialization.json)
implementation(libs.ktor.server.data.conversion)
implementation(libs.mongodb.bson)
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(11)
}
val javadocJar by tasks.register<Jar>("dokkaJavadocJar") {
dependsOn(tasks.dokkaJavadoc)
from(tasks.dokkaJavadoc.flatMap { it.outputDirectory })
archiveClassifier.set("javadoc")
}
val sourcesJar by tasks.register<Jar>("sourcesJar") {
from(sourceSets.main.get().allSource)
archiveClassifier.set("sources")
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = rootProject.group.toString()
artifactId = "json-core"
version = rootProject.version.toString()
from(components["java"])
artifact(javadocJar)
artifact(sourcesJar)
}
}
repositories {
val secretFile = rootProject.file("secret.properties")
if (secretFile.exists()) {
val secret = Properties()
secretFile.inputStream().also { secret.load(it) }
val mavenUrl = secret["neuon.maven.url"] as? String
val mavenUsername = secret["neuon.maven.username"] as? String
val mavenPassword = secret["neuon.maven.password"] as? String
if (mavenUrl != null && mavenUsername != null && mavenPassword != null) {
maven {
requireNotNull(mavenUrl) {
"neuon.maven.url is missing from secret.properties"
}
requireNotNull(mavenUsername) {
"neuon.maven.username is missing from secret.properties"
}
requireNotNull(mavenPassword) {
"neuon.maven.password is missing from secret.properties"
}
name = "neuon"
url = uri(mavenUrl)
credentials(PasswordCredentials::class) {
username = mavenUsername
password = mavenPassword
}
}
} else {
val list = listOfNotNull(
"neuon.maven.url".takeIf { mavenUrl == null },
"neuon.maven.username".takeIf { mavenUsername == null },
"neuon.maven.password".takeIf { mavenPassword == null },
)
val message = buildString {
append("Missing Maven publication in secret.properties: ")
append(list.joinToString())
append(". Ignore this if you don't plan on publishing this library")
}
logger.error(message)
}
} else {
logger.error(
buildString {
append("Missing secret.properties. Ignore this if you don't plan on publishing this library")
},
)
}
}
}

View File

@@ -0,0 +1,170 @@
package ai.neuon.utility.json
import kotlinx.datetime.Instant
import kotlinx.serialization.json.*
/**
* @throws IllegalArgumentException if the current element is not a [String]
*/
fun JsonElement.asString(): String {
val primitive = jsonPrimitive
if (primitive.isString) {
return primitive.content
}
throw IllegalArgumentException("Element is not a string")
}
/**
* @return null if element is not a [String]
*/
fun JsonElement.asStringOrNull(): String? {
return try {
asString()
} catch (_: IllegalArgumentException) {
null
}
}
/**
* @throws IllegalArgumentException if the current element is not a [Long]
* @throws NumberFormatException if the current element is an invalid number
*/
fun JsonElement.asLong(): Long {
return jsonPrimitive.long
}
/**
* @return null if element is not a [Long]
*/
fun JsonElement.asLongOrNull(): Long? {
return try {
asLong()
} catch (_: IllegalArgumentException) {
null
} catch (_: NumberFormatException) {
null
}
}
/**
* @throws IllegalArgumentException if the current element is not a [Float]
* @throws NumberFormatException if the current element is an invalid number
*/
fun JsonElement.asFloat(): Float {
return jsonPrimitive.float
}
/**
* @return null if element is not a [Float]
*/
fun JsonElement.asFloatOrNull(): Float? {
return try {
asFloat()
} catch (_: IllegalArgumentException) {
null
} catch (_: NumberFormatException) {
null
}
}
/**
* @throws IllegalArgumentException if the current element is not a [Double]
* @throws NumberFormatException if the current element is an invalid number
*/
fun JsonElement.asDouble(): Double {
return jsonPrimitive.double
}
/**
* @return null if element is not a [Double]
*/
fun JsonElement.asDoubleOrNull(): Double? {
return try {
asDouble()
} catch (_: IllegalArgumentException) {
null
} catch (_: NumberFormatException) {
null
}
}
/**
* @throws IllegalArgumentException if the current element is not a [Boolean]
* @throws NumberFormatException if the current element is an invalid boolean
*/
fun JsonElement.asBoolean(): Boolean {
return jsonPrimitive.boolean
}
/**
* @return null if element is not a [Boolean]
*/
fun JsonElement.asBooleanOrNull(): Boolean? {
return try {
asBoolean()
} catch (_: IllegalArgumentException) {
null
} catch (_: NumberFormatException) {
null
}
}
/**
* @throws IllegalArgumentException if the current element is not a valid ISO 8601 [String]
*/
fun JsonElement.asInstant(): Instant {
val value = try {
asString()
} catch (e: IllegalArgumentException) {
throw IllegalArgumentException("Element must be in extended ISO 8601 string", e)
}
return Instant.parse(value)
}
/**
* @return null if the current element is not a valid ISO 8601 [String]
*/
fun JsonElement.asInstantOrNull(): Instant? {
return try {
asInstant()
} catch (_: IllegalArgumentException) {
null
}
}
/**
* @throws IllegalArgumentException if the current element is not a [JsonObject]
*/
fun JsonElement.asJsonObject(): JsonObject {
return jsonObject
}
/**
* @return null if element is not a [JsonObject]
*/
fun JsonElement.asJsonObjectOrNull(): JsonObject? {
return try {
asJsonObject()
} catch (_: IllegalArgumentException) {
null
}
}
/**
* @throws IllegalArgumentException if the current element is not a [JsonArray]
*/
fun JsonElement.asJsonArray(): JsonArray {
return jsonArray
}
/**
* @return null if element is not a [JsonArray]
*/
fun JsonElement.asJsonArrayOrNull(): JsonArray? {
return try {
asJsonArray()
} catch (_: IllegalArgumentException) {
null
}
}

View File

@@ -0,0 +1,20 @@
package ai.neuon.utility.json
import kotlinx.datetime.Instant
import kotlinx.serialization.json.JsonObjectBuilder
import kotlinx.serialization.json.put
import org.bson.types.ObjectId
import kotlin.time.Duration
fun JsonObjectBuilder.put(key: String, instant: Instant) {
put(key = key, value = instant.toString())
}
fun JsonObjectBuilder.put(key: String, duration: Duration) {
put(key = key, value = duration.toIsoString())
}
fun JsonObjectBuilder.put(key: String, id: ObjectId) {
put(key = key, value = id.toHexString())
}