Compare commits

..

No commits in common. "master" and "4.3.3" have entirely different histories.

160 changed files with 2717 additions and 11911 deletions

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils * ModuleName mingli-utils
* CurrentFile build.gradle.kts * CurrentFile build.gradle.kts
* LastUpdate 2026-02-08 03:14:06 * LastUpdate 2026-01-08 11:10:03
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -31,7 +31,6 @@ plugins {
`maven-publish` `maven-publish`
kotlin("jvm") version "2.2.20" kotlin("jvm") version "2.2.20"
id("org.jetbrains.dokka") version "2.0.0" id("org.jetbrains.dokka") version "2.0.0"
kotlin("kapt") version "2.2.20"
} }
val GROUPSID = project.properties["GROUPSID"] as String val GROUPSID = project.properties["GROUPSID"] as String
val VERSIONS = project.properties["VERSIONS"] as String val VERSIONS = project.properties["VERSIONS"] as String
@ -60,10 +59,6 @@ sourceSets {
} }
} }
tasks.test {
useJUnitPlatform()
}
java { java {
withSourcesJar() withSourcesJar()
toolchain.languageVersion.set(JavaLanguageVersion.of(8)) toolchain.languageVersion.set(JavaLanguageVersion.of(8))
@ -72,28 +67,19 @@ java {
dependencies { dependencies {
implementation("org.slf4j:slf4j-api:2.0.17") implementation("org.slf4j:slf4j-api:2.0.17")
implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1")
implementation(kotlin("reflect"))
implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1")
compileOnly("org.mindrot:jbcrypt:0.4") compileOnly("org.mindrot:jbcrypt:0.4")
compileOnly("com.squareup.okhttp3:okhttp:5.3.2") compileOnly("org.springframework.boot:spring-boot-starter:2.7.14")
compileOnly("com.fasterxml.jackson.core:jackson-databind:2.21.0") compileOnly("com.fasterxml.jackson.core:jackson-databind:2.19.2")
compileOnly("com.fasterxml.jackson.module:jackson-module-kotlin:2.21.0") compileOnly("com.google.code.gson:gson:2.13.1")
compileOnly("org.springframework.boot:spring-boot-starter-web:2.7.18")
compileOnly("com.google.code.gson:gson:2.13.2")
compileOnly("org.mybatis:mybatis:3.5.19") compileOnly("org.mybatis:mybatis:3.5.19")
compileOnly("com.alibaba.fastjson2:fastjson2:2.0.58")
compileOnly("io.netty:netty-all:4.1.130.Final") compileOnly("io.netty:netty-all:4.1.130.Final")
compileOnly("com.baomidou:mybatis-plus-core:3.5.15")
compileOnly("com.baomidou:mybatis-plus-core:3.0.1")
compileOnly("net.java.dev.jna:jna:5.17.0") compileOnly("net.java.dev.jna:jna:5.17.0")
compileOnly("com.baomidou:mybatis-plus-extension:3.5.15")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
// testImplementation("com.squareup.okhttp3:okhttp:5.3.2")
testImplementation("com.mingliqiye.logger:logger-log4j2:1.0.5")
testImplementation("com.google.code.gson:gson:2.13.2")
testImplementation("com.fasterxml.jackson.core:jackson-databind:2.21.0")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.21.0")
} }
@ -108,15 +94,6 @@ tasks.withType<JavaExec>().configureEach {
) )
} }
kapt {
arguments {
arg(
"kapt.kotlin.generated",
project.layout.buildDirectory.dir("generated/source/kapt/main").get().asFile.absolutePath
)
}
}
tasks.withType<org.gradle.jvm.tasks.Jar> { tasks.withType<org.gradle.jvm.tasks.Jar> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from("LICENSE") { into("META-INF") } from("LICENSE") { into("META-INF") }
@ -149,8 +126,6 @@ tasks.withType<org.gradle.jvm.tasks.Jar> {
} }
val isJdk8Build = project.findProperty("buildForJdk8") == "true" val isJdk8Build = project.findProperty("buildForJdk8") == "true"
repositories { repositories {
maven { maven {
url = uri("https://maven.aliyun.com/repository/public/") url = uri("https://maven.aliyun.com/repository/public/")
@ -227,7 +202,7 @@ tasks.build {
tasks.processResources { tasks.processResources {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
outputs.upToDateWhen { false } outputs.upToDateWhen { false }
filesMatching(listOf("META-INF/meta-data", "fabric.mod.json")) { filesMatching("META-INF/meta-data") {
expand( expand(
project.properties + mapOf( project.properties + mapOf(
"buildTime" to LocalDateTime.now().format( "buildTime" to LocalDateTime.now().format(

View File

@ -16,13 +16,13 @@
# ProjectName mingli-utils # ProjectName mingli-utils
# ModuleName mingli-utils # ModuleName mingli-utils
# CurrentFile gradle.properties # CurrentFile gradle.properties
# LastUpdate 2026-02-08 03:15:06 # LastUpdate 2026-01-10 08:55:10
# UpdateUser MingLiPro # UpdateUser MingLiPro
# #
JDKVERSIONS=1.8 JDKVERSIONS=1.8
GROUPSID=com.mingliqiye.utils GROUPSID=com.mingliqiye.utils
ARTIFACTID=mingli-utils ARTIFACTID=mingli-utils
VERSIONS=4.6.4 VERSIONS=4.3.3
signing.keyId=B22AA93B signing.keyId=B22AA93B
signing.password= signing.password=
signing.secretKeyRingFile=secret.gpg signing.secretKeyRingFile=secret.gpg

View File

@ -24,6 +24,8 @@ plugins {
id("java-library") id("java-library")
id("maven-publish") id("maven-publish")
signing signing
kotlin("jvm") version "2.2.20"
id("org.jetbrains.dokka") version "2.0.0"
} }
val GROUPSID = project.properties["GROUPSID"] as String val GROUPSID = project.properties["GROUPSID"] as String
val VERSIONS = project.properties["VERSIONS"] as String val VERSIONS = project.properties["VERSIONS"] as String
@ -82,7 +84,6 @@ publishing {
} }
java.toolchain.languageVersion.set(JavaLanguageVersion.of(8)) java.toolchain.languageVersion.set(JavaLanguageVersion.of(8))
dependencies { dependencies {
api(rootProject) api(rootProject)
implementation("com.mingliqiye.utils.jna:WinKernel32Platform:1.0.1") implementation("com.mingliqiye.utils.jna:WinKernel32Platform:1.0.1")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils * ModuleName mingli-utils
* CurrentFile settings.gradle.kts * CurrentFile settings.gradle.kts
* LastUpdate 2026-02-07 17:00:59 * LastUpdate 2025-09-16 12:32:52
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */

File diff suppressed because it is too large Load Diff

View File

@ -15,20 +15,28 @@
* *
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile StringToUUIDConverter.kt * CurrentFile Main.kt
* LastUpdate 2026-02-04 21:58:01 * LastUpdate 2026-01-06 14:04:14
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.springboot.converters package com.mingliqiye.utils
import com.mingliqiye.utils.network.NetworkEndpoint
import com.mingliqiye.utils.uuid.UUID import com.mingliqiye.utils.uuid.UUID
import org.springframework.core.convert.converter.Converter import java.nio.ByteBuffer
import org.springframework.stereotype.Component
fun main() {
val byteBuffer = ByteBuffer.allocate(320)
NetworkEndpoint
.of("0:65532")
.writeIpv4toByteBuffer(byteBuffer)
UUID.getMaxUUID().writeToByteBuffer(byteBuffer)
byteBuffer.flip()
println(NetworkEndpoint.ofIpv4(byteBuffer))
println(UUID.of(byteBuffer))
@Component
class StringToUUIDConverter : Converter<String, UUID> {
override fun convert(source: String): UUID {
return UUID.of(source)
}
} }

View File

@ -1,41 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile AutoService.kt
* LastUpdate 2026-02-07 17:00:39
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation
import kotlin.reflect.KClass
/**
* 标记一个类为其提供自动服务注册功能的注解
*
* 此注解用于标识那些需要被自动注册为服务的类通过指定[value]参数
* 可以声明该类实现的服务接口类型注解的作用范围限定为类CLASS
* 并且仅在源码级别保留SOURCE不会编译到字节码中
* @since 4.6.3
*
* @param value 需要注册的服务接口类型数组默认为空数组
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class AutoService(
val value: Array<KClass<*>> = []
)

View File

@ -1,39 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile DateTimeJsonFormat.kt
* LastUpdate 2026-02-07 08:05:39
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation
import com.mingliqiye.utils.time.Formatter
/**
* 日期时间JSON格式化注解用于标注字段的日期时间格式化方式
*
* @property value 格式化器类型默认为NONE
* @property formatter 自定义格式化字符串默认为空字符串
* @property repcZero 是否替换零值默认为true
*/
@Target(AnnotationTarget.FIELD)
annotation class DateTimeJsonFormat(
val value: Formatter = Formatter.NONE,
val formatter: String = "",
val repcZero: Boolean = true,
)

View File

@ -1,31 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile TestAnnotation.kt
* LastUpdate 2026-02-07 08:44:25
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
annotation class TestAnnotation(val value: String = "test")
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.SOURCE)
annotation class TestFieldAnnotation(val required: Boolean = true)

View File

@ -1,38 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UUIDJsonFormat.kt
* LastUpdate 2026-02-07 08:05:58
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation
import com.mingliqiye.utils.base.BaseType
import com.mingliqiye.utils.uuid.UUIDFormatType
/**
* UUID JSON格式化注解用于指定UUID字段在JSON序列化/反序列化时的格式
*
* @property value UUID格式类型默认为 NO_UPPER_SPACE
* @property base 基数类型默认为 BASE16
*/
@Target(AnnotationTarget.FIELD)
annotation class UUIDJsonFormat(
val value: UUIDFormatType = UUIDFormatType.NO_UPPER_SPACE,
val base: BaseType = BaseType.BASE16
)

View File

@ -1,105 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile AutoServiceProcessor.kt
* LastUpdate 2026-02-08 01:24:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation.processor
import com.mingliqiye.utils.annotation.AutoService
import com.mingliqiye.utils.io.IO.println
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.RoundEnvironment
import javax.annotation.processing.SupportedAnnotationTypes
import javax.lang.model.element.TypeElement
import javax.lang.model.type.MirroredTypesException
import javax.lang.model.type.TypeMirror
import javax.tools.StandardLocation
@SupportedAnnotationTypes("com.mingliqiye.utils.annotation.AutoService")
class AutoServiceProcessor : AbstractProcessor() {
override fun init(processingEnv: ProcessingEnvironment) {
super.init(processingEnv)
}
override fun process(
annotations: Set<TypeElement>,
roundEnv: RoundEnvironment
): Boolean {
val service = mutableMapOf<String, MutableList<String>>()
val elements = roundEnv.getElementsAnnotatedWith(AutoService::class.java)
if (elements.isEmpty()) return false
for (element in elements) {
val autoServiceAnnotation = element.getAnnotation(AutoService::class.java)
var asd = (try {
autoServiceAnnotation!!.value.map { it.java.name }
} catch (e: MirroredTypesException) {
e.typeMirrors.map(TypeMirror::toString)
})
if (asd.isEmpty()) {
if (element is TypeElement) {
asd = element.interfaces.map { it.toString() }
}
}
for (data in asd) {
var ldata: MutableList<String>? = service[data]
if (ldata == null) {
ldata = mutableListOf()
service[data] = ldata
}
ldata.add(element.toString())
}
}
processClassAnnotation(service)
return true
}
fun processClassAnnotation(map: Map<String, MutableList<String>>) {
map.forEach { (interfaceName, implementations) ->
if (implementations.isEmpty()) {
println("警告: $interfaceName 的实现列表为空!")
return@forEach
}
try {
val serviceFile = processingEnv.filer.createResource(
StandardLocation.CLASS_OUTPUT,
"",
"META-INF/services/$interfaceName"
)
val content = StringBuilder()
serviceFile.openWriter().use { writer ->
implementations.forEach { impl ->
val line = "$impl\n"
content.append(line)
writer.write(line)
}
writer.flush()
}
} catch (e: Exception) {
println("文件创建失败: ${e.javaClass.name} - ${e.message}")
e.printStackTrace()
}
}
}
}

View File

@ -1,342 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ArrayUtils.kt
* LastUpdate 2026-02-06 14:01:56
* UpdateUser MingLiPro
*/
@file:JvmName("ArrayUtils")
package com.mingliqiye.utils.array
import com.mingliqiye.utils.base.BASE16
/**
* 将字节数组转换为十六进制字符串
*
* @return 大写的十六进制字符串每两个字符表示一个字节
* @since 4.6.0
* @see toHexByteArray
*/
fun ByteArray.toHexString(): String = BASE16.encode(this).uppercase()
/**
* 将十六进制字符串转换为字节数组
*
* @return 对应的字节数组
* @throws IllegalArgumentException 如果字符串包含非十六进制字符
* @since 4.6.0
* @see toHexString
*/
fun String.toHexByteArray(): ByteArray = BASE16.decode(this.lowercase())
/* ==================== 数组复制扩展函数 ==================== */
/**
* 将当前数组的指定范围复制到目标数组
*
* @param dest 目标数组
* @param srcPos 源数组起始位置包含
* @param distPos 目标数组起始位置包含
* @param len 要复制的元素数量
* @return 源数组自身支持链式调用
* @throws IndexOutOfBoundsException 如果索引超出范围
* @throws IllegalArgumentException 如果参数无效
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun <T> Array<T>.copyTo(dest: Array<T>, srcPos: Int, distPos: Int, len: Int): Array<T> = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 创建新数组并复制当前数组的指定范围
*
* @param srcPos 源数组起始位置包含
* @param distPos 目标数组起始位置包含
* @param len 要复制的元素数量也作为新数组的长度
* @return 新创建的数组
* @throws IndexOutOfBoundsException 如果索引超出范围
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun <T> Array<T>.copyTo(srcPos: Int, distPos: Int, len: Int): Array<T> =
java.lang.reflect.Array.newInstance(this.javaClass.componentType, len).also {
System.arraycopy(this, srcPos, it, distPos, len)
}.let {
@Suppress("UNCHECKED_CAST")
it as Array<T>
}
/**
* 将源数组的指定范围复制到当前数组
*
* @param src 源数组
* @param srcPos 源数组起始位置包含
* @param distPos 当前数组起始位置包含
* @param len 要复制的元素数量
* @return 当前数组自身支持链式调用
* @throws IndexOutOfBoundsException 如果索引超出范围
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun <T> Array<T>.copyFrom(src: Array<T>, srcPos: Int, distPos: Int, len: Int): Array<T> = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== BooleanArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun BooleanArray.copyTo(dest: BooleanArray, srcPos: Int, distPos: Int, len: Int): BooleanArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun BooleanArray.copyTo(srcPos: Int, distPos: Int, len: Int): BooleanArray =
BooleanArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun BooleanArray.copyFrom(src: BooleanArray, srcPos: Int, distPos: Int, len: Int): BooleanArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== ByteArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun ByteArray.copyTo(dest: ByteArray, srcPos: Int, distPos: Int, len: Int): ByteArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun ByteArray.copyTo(srcPos: Int, distPos: Int, len: Int): ByteArray =
ByteArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun ByteArray.copyFrom(src: ByteArray, srcPos: Int, distPos: Int, len: Int): ByteArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== CharArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun CharArray.copyTo(dest: CharArray, srcPos: Int, distPos: Int, len: Int): CharArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun CharArray.copyTo(srcPos: Int, distPos: Int, len: Int): CharArray =
CharArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun CharArray.copyFrom(src: CharArray, srcPos: Int, distPos: Int, len: Int): CharArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== DoubleArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun DoubleArray.copyTo(dest: DoubleArray, srcPos: Int, distPos: Int, len: Int): DoubleArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun DoubleArray.copyTo(srcPos: Int, distPos: Int, len: Int): DoubleArray =
DoubleArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun DoubleArray.copyFrom(src: DoubleArray, srcPos: Int, distPos: Int, len: Int): DoubleArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== FloatArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun FloatArray.copyTo(dest: FloatArray, srcPos: Int, distPos: Int, len: Int): FloatArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun FloatArray.copyTo(srcPos: Int, distPos: Int, len: Int): FloatArray =
FloatArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun FloatArray.copyFrom(src: FloatArray, srcPos: Int, distPos: Int, len: Int): FloatArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== IntArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun IntArray.copyTo(dest: IntArray, srcPos: Int, distPos: Int, len: Int): IntArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun IntArray.copyTo(srcPos: Int, distPos: Int, len: Int): IntArray =
IntArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun IntArray.copyFrom(src: IntArray, srcPos: Int, distPos: Int, len: Int): IntArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== LongArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun LongArray.copyTo(dest: LongArray, srcPos: Int, distPos: Int, len: Int): LongArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun LongArray.copyTo(srcPos: Int, distPos: Int, len: Int): LongArray =
LongArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun LongArray.copyFrom(src: LongArray, srcPos: Int, distPos: Int, len: Int): LongArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== ShortArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun ShortArray.copyTo(dest: ShortArray, srcPos: Int, distPos: Int, len: Int): ShortArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* @see Array.copyTo
* @since 4.6.2
*/
@JvmName("arrayCopy")
fun ShortArray.copyTo(srcPos: Int, distPos: Int, len: Int): ShortArray =
ShortArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun ShortArray.copyFrom(src: ShortArray, srcPos: Int, distPos: Int, len: Int): ShortArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}

View File

@ -1,68 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Base10.kt
* LastUpdate 2026-02-08 03:08:10
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.base
import java.math.BigInteger
internal class Base10 : BaseCodec {
/**
* 将字节数组编码为Base10字符串十进制
*
* @param bytes 需要编码的字节数组
* @return 编码后的Base10字符串十进制数字
*/
override fun encode(bytes: ByteArray): String {
if (bytes.isEmpty()) return "0"
// 将字节数组转换为正的大整数
val bigInt = BigInteger(1, bytes) // 参数1表示正数
return bigInt.toString(10) // 转换为10进制字符串
}
/**
* 将Base10字符串解码为字节数组
*
* @param string 需要解码的Base10字符串十进制数字
* @return 解码后的字节数组
*/
override fun decode(string: String): ByteArray {
// 验证输入是否为有效的十进制数字
if (!string.matches(Regex("\\d+"))) {
throw IllegalArgumentException("Base10字符串只能包含数字0-9")
}
val bigInt = BigInteger(string, 10) // 从10进制解析
// 转换为字节数组,并确保保留前导零
var byteArray = bigInt.toByteArray()
// BigInteger.toByteArray() 可能会添加一个符号字节
// 对于正数如果第一个字节是0需要移除它
if (byteArray.isNotEmpty() && byteArray[0] == 0.toByte()) {
byteArray = byteArray.copyOfRange(1, byteArray.size)
}
return byteArray
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Base16.kt * CurrentFile Base16.kt
* LastUpdate 2026-02-08 03:08:10 * LastUpdate 2025-09-17 10:56:07
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -26,7 +26,7 @@ package com.mingliqiye.utils.base
* Base16编解码器实现类 * Base16编解码器实现类
* 提供字节数组与十六进制字符串之间的相互转换功能 * 提供字节数组与十六进制字符串之间的相互转换功能
*/ */
internal class Base16 : BaseCodec { class Base16 : BaseCodec {
/** /**
* 将字节数组编码为十六进制字符串 * 将字节数组编码为十六进制字符串
* @param bytes 待编码的字节数组 * @param bytes 待编码的字节数组

View File

@ -1,59 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Base2.kt
* LastUpdate 2026-02-08 03:06:23
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.base
internal class Base2 : BaseCodec {
override fun encode(bytes: ByteArray): String {
if (bytes.isEmpty()) return ""
val result = StringBuilder()
for ((index, byte) in bytes.withIndex()) {
val unsignedByte = byte.toInt() and 0xFF
val binary = unsignedByte.toString(2).padStart(8, '0')
result.append(binary)
}
return result.toString()
}
override fun decode(string: String): ByteArray {
if (string.length % 8 != 0) {
throw IllegalArgumentException(
"BASE1字符串长度必须是8的倍数当前长度: ${string.length}"
)
}
if (!string.matches(Regex("[01]+"))) {
throw IllegalArgumentException(
"BASE1字符串只能包含字符'0'和'1'"
)
}
val byteCount = string.length / 8
val result = ByteArray(byteCount)
for (i in 0 until byteCount) {
val startIndex = i * 8
val endIndex = startIndex + 8
val binaryStr = string.substring(startIndex, endIndex)
val byteValue = binaryStr.toInt(2)
result[i] = byteValue.toByte()
}
return result
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Base256.kt * CurrentFile Base256.kt
* LastUpdate 2026-02-08 03:08:10 * LastUpdate 2025-09-20 14:01:29
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -30,7 +30,7 @@ package com.mingliqiye.utils.base
* !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~§±×÷ * !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~§±×÷
* *
*/ */
internal class Base256 : BaseCodec { class Base256 : BaseCodec {
companion object { companion object {
val code = arrayOf( val code = arrayOf(

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Base64.kt * CurrentFile Base64.kt
* LastUpdate 2026-02-08 03:08:10 * LastUpdate 2025-09-17 10:56:32
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -26,7 +26,7 @@ package com.mingliqiye.utils.base
* Base64编解码工具类 * Base64编解码工具类
* 提供Base64编码和解码功能的实现 * 提供Base64编码和解码功能的实现
*/ */
internal class Base64 : BaseCodec { class Base64 : BaseCodec {
/* /*
* Base64编码器实例 * Base64编码器实例

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Base91.kt * CurrentFile Base91.kt
* LastUpdate 2026-02-08 03:08:10 * LastUpdate 2025-09-19 20:08:46
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -27,7 +27,7 @@ package com.mingliqiye.utils.base
* *
* Base91 是一种高效的二进制到文本的编码方式相较于 Base64它使用更少的字符来表示相同的数据 * Base91 是一种高效的二进制到文本的编码方式相较于 Base64它使用更少的字符来表示相同的数据
*/ */
internal class Base91 : BaseCodec { class Base91 : BaseCodec {
companion object { companion object {
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile BaseUtils.kt * CurrentFile BaseUtils.kt
* LastUpdate 2026-02-08 03:00:37 * LastUpdate 2025-09-19 20:18:09
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -24,49 +24,40 @@
package com.mingliqiye.utils.base package com.mingliqiye.utils.base
import com.mingliqiye.utils.base.code.Base10 /**
import com.mingliqiye.utils.base.code.Base16 * Base64编解码器实例
import com.mingliqiye.utils.base.code.Base256 * 使用懒加载方式初始化Base64编解码器对象
import com.mingliqiye.utils.base.code.Base64 * 保证线程安全且只在首次访问时创建实例
import com.mingliqiye.utils.base.code.Base91 */
val BASE64: BaseCodec by lazy {
Base64()
}
/**
* Base91编解码器实例
* 使用懒加载方式初始化Base91编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE91: BaseCodec by lazy {
Base91()
}
/**
* Base91编解码器实例
* 使用懒加载方式初始化Base91编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE16: BaseCodec by lazy {
Base16()
}
/**
* Base256编解码器实例
* 使用懒加载方式初始化Base256编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE256: BaseCodec by lazy {
Base256()
}
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base10", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE10: BaseCodec
get() = Base10
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base16", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE16: BaseCodec
get() = Base16
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base64", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE64: BaseCodec
get() = Base64
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base91", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE91: BaseCodec
get() = Base91
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base256", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE256: BaseCodec
get() = Base256

View File

@ -1,81 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseCodes.kt
* LastUpdate 2026-02-08 03:10:03
* UpdateUser MingLiPro
*/
@file:JvmName("BaseCodes")
package com.mingliqiye.utils.base.code
import com.mingliqiye.utils.base.*
/**
* 提供Base2编码器的懒加载实例
* 该编码器用于将数据编码为二进制格式
*/
@get:JvmName("Base2")
val Base2: BaseCodec by lazy {
Base2()
}
/**
* 提供Base10编码器的懒加载实例
* 该编码器用于将数据编码为十进制格式
*/
@get:JvmName("Base10")
val Base10: BaseCodec by lazy {
Base10()
}
/**
* 提供Base16编码器的懒加载实例
* 该编码器用于将数据编码为十六进制格式
*/
@get:JvmName("Base16")
val Base16: BaseCodec by lazy {
Base16()
}
/**
* 提供Base64编码器的懒加载实例
* 该编码器用于将数据编码为Base64格式常用于URL安全传输或存储
*/
@get:JvmName("Base64")
val Base64: BaseCodec by lazy {
Base64()
}
/**
* 提供Base91编码器的懒加载实例
* 该编码器用于将数据编码为Base91格式具有较高的压缩效率
*/
@get:JvmName("Base91")
val Base91: BaseCodec by lazy {
Base91()
}
/**
* 提供Base256编码器的懒加载实例
* 该编码器用于将数据编码为Base256格式适用于字节级数据处理
*/
@get:JvmName("Base256")
val Base256: BaseCodec by lazy {
Base256()
}

View File

@ -16,16 +16,14 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile ByteBufferUtils.kt * CurrentFile ByteBufferUtils.kt
* LastUpdate 2026-01-11 09:44:19 * LastUpdate 2026-01-07 10:01:45
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("ByteBufferUtils") @file:JvmName("ByteBufferUtil")
package com.mingliqiye.utils.bytes package com.mingliqiye.utils.bytes
import java.io.IOException
import java.io.OutputStream
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.charset.Charset import java.nio.charset.Charset
@ -205,93 +203,3 @@ fun ByteBuffer.putBoolean(boolean: Boolean): ByteBuffer = this.put(if (boolean)
fun ByteArray.toByteBuffer(): ByteBuffer { fun ByteArray.toByteBuffer(): ByteBuffer {
return ByteBuffer.wrap(this) return ByteBuffer.wrap(this)
} }
/**
* 从ByteBuffer中读取一个变长整数VarNumber
*
* 变长整数使用可变长度编码方式每个字节的最高位表示是否还有后续字节
* - 如果最高位为1则表示还有下一个字节
* - 如果最高位为0则表示当前字节是最后一个字节
*
* @param size 最大允许读取的字节数默认为8即Long类型的最大长度
* @return 解码后的长整型数值
* @throws IOException 当读取过程中发生IO异常时抛出
*/
fun ByteBuffer.getVarLong(size: Int = 8): Long {
var numRead = 0
var result: Long = 0
var read: Byte
do {
read = this.get()
// 将当前字节的有效7位数据左移相应位置后与结果进行按位或运算
result = result or ((read.toLong() and 127) shl (7 * numRead))
numRead++
if (numRead > size) {
throw IOException("VarNumber is too big")
}
} while ((read.toLong() and 128) != 0L)
return result
}
/**
* 从ByteBuffer中读取一个变长整数VarNumber返回Int类型
*
* @return 解码后的整型数值
*/
fun ByteBuffer.getVarInt(): Int = this.getVarLong(4).toInt()
/**
* 从ByteBuffer中读取一个变长整数VarNumber返回Short类型
*
* @return 解码后的短整型数值
*/
fun ByteBuffer.getVarShort(): Short = this.getVarLong(2).toShort()
/**
* 从输入流中读取一个变长长整数VarLong最大长度默认为8个字节
*
* @return 解码后的长整型数值
* @throws IOException 当读取过程中发生IO异常时抛出
*/
@Throws(IOException::class)
fun ByteBuffer.getVarLong(): Long = this.getVarLong(8)
/**
* 将长整型数值编码为变长格式并写入ByteBuffer
*
* 变长整数使用可变长度编码方式每个字节的最高位表示是否还有后续字节
* - 如果数值还有更多字节则最高位设为1
* - 最后一个字节最高位设为0
*
* @param value 要写入的长整型数值
* @return 当前ByteBuffer实例支持链式调用
*/
fun ByteBuffer.putVarLong(value: Long): ByteBuffer {
var v = value
while (v >= 0x80) {
this.put((v and 0x7F or 0x80).toByte())
v = v shr 7
}
this.put(v.toByte())
return this
}
/**
* 将整型数值编码为变长格式并写入ByteBuffer
*
* @param value 要写入的整型数值
* @return 当前ByteBuffer实例支持链式调用
*/
fun ByteBuffer.putVarInt(value: Int): ByteBuffer = this.putVarLong(value.toLong())
/**
* 将短整型数值编码为变长格式并写入ByteBuffer
*
* @param value 要写入的短整型数值
* @return 当前ByteBuffer实例支持链式调用
*/
fun ByteBuffer.putVarShort(value: Short): ByteBuffer = this.putVarLong(value.toLong())
fun ByteBuffer.writeStream(outputStream: OutputStream) = outputStream.write(this.toByteArray())

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,74 +16,28 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile ByteUtils.kt * CurrentFile ByteUtils.kt
* LastUpdate 2026-01-14 13:01:44 * LastUpdate 2025-09-20 11:49:05
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("ByteUtils") @file:JvmName("ByteUtils")
package com.mingliqiye.utils.bytes package com.mingliqiye.utils.bytes
import com.mingliqiye.utils.base.BASE16
import com.mingliqiye.utils.stream.SuperStream import com.mingliqiye.utils.stream.SuperStream
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_ASC: Byte = 0x10 const val ESC_ASC: Byte = 0x10
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_DESC: Byte = 0x1B const val ESC_DESC: Byte = 0x1B
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_NONE: Byte = 0x00 const val ESC_NONE: Byte = 0x00
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_START: Byte = 0x01 const val ESC_START: Byte = 0x01
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_END: Byte = 0x02 const val ESC_END: Byte = 0x02
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_ESC: Byte = 0x03 const val ESC_ESC: Byte = 0x03
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_CONTROL: Byte = 0x04 const val ESC_CONTROL: Byte = 0x04
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_DATA: Byte = 0x05 const val ESC_DATA: Byte = 0x05
/**
* 转义字符常量定义
* 定义了用于数据传输或协议通信中的特殊控制字节值
*/
const val ESC_RESERVED: Byte = 0x06 const val ESC_RESERVED: Byte = 0x06
/** /**
* 将字节数组转换为十六进制字符串列表 * 将字节数组转换为十六进制字符串列表
* @receiver 字节数组
* @return 包含每个字节对应十六进制字符串的列表 * @return 包含每个字节对应十六进制字符串的列表
*/ */
fun ByteArray.getByteArrayString(): MutableList<String> { fun ByteArray.getByteArrayString(): MutableList<String> {
@ -92,12 +46,6 @@ fun ByteArray.getByteArrayString(): MutableList<String> {
} }
/**
* 将十六进制字符转换为对应的数值
* @receiver 十六进制字符
* @return 对应的数值0-15
* @throws NumberFormatException 当字符不是有效的十六进制字符时抛出
*/
fun Char.hexDigitToValue(): Int { fun Char.hexDigitToValue(): Int {
return when (this) { return when (this) {
in '0'..'9' -> this - '0' in '0'..'9' -> this - '0'
@ -107,23 +55,6 @@ fun Char.hexDigitToValue(): Int {
} }
} }
/** private fun hexStringToByteArray(string: String): ByteArray {
* 将十六进制字符串转换为字节数组
*
* @param string 输入的十六进制字符串
* @return 转换后的字节数组
*/
fun hexStringToByteArray(string: String): ByteArray {
return string.hexToByteArray() return string.hexToByteArray()
} }
/**
* 将字节数组转换为十六进制字符串表示
*
* @param bytes 输入的字节数组
* @return 对应的十六进制字符串
*/
fun bytesToHex(bytes: ByteArray): String {
return BASE16.encode(bytes)
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,15 +16,15 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile CloneUtils.kt * CurrentFile CloneUtils.kt
* LastUpdate 2026-02-05 14:41:27 * LastUpdate 2025-09-20 14:01:29
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("CloneUtils") @file:JvmName("CloneUtils")
package com.mingliqiye.utils.clone package com.mingliqiye.utils.clone
import com.mingliqiye.utils.exception.JsonException import com.mingliqiye.utils.json.JsonApi
import com.mingliqiye.utils.json.api.base.JsonApi import com.mingliqiye.utils.json.JsonException
import java.io.* import java.io.*
@ -34,7 +34,8 @@ inline fun <reified T> Serializable.deepClone(): T {
inline fun <reified T> T.deepJsonClone(jsonApi: JsonApi): T { inline fun <reified T> T.deepJsonClone(jsonApi: JsonApi): T {
try { try {
return jsonApi.convert(this as Any, this!!.javaClass) as T return jsonApi.convert(this, this!!.javaClass) as T
} catch (e: Exception) { } catch (e: Exception) {
throw JsonException( throw JsonException(
"Failed to deep clone object using JSON", e "Failed to deep clone object using JSON", e

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile IsChanged.kt * CurrentFile IsChanged.kt
* LastUpdate 2026-01-31 21:13:45 * LastUpdate 2025-09-19 20:17:07
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -39,14 +39,17 @@ class IsChanged<T> {
*/ */
private val atomicReferenceData: AtomicReference<T> = AtomicReference() private val atomicReferenceData: AtomicReference<T> = AtomicReference()
constructor() /**
* 默认构造函数初始化数据为 null
*/
constructor() : this(null)
/** /**
* 带参数的构造函数使用指定的初始值初始化 * 带参数的构造函数使用指定的初始值初始化
* *
* @param data 初始数据值 * @param data 初始数据值
*/ */
constructor(data: T) : super() { constructor(data: T?) : super() {
atomicReferenceData.set(data) atomicReferenceData.set(data)
} }
@ -64,7 +67,7 @@ class IsChanged<T> {
* *
* @return 当前数据值 * @return 当前数据值
*/ */
fun get(): T { fun get(): T? {
return atomicReferenceData.get() return atomicReferenceData.get()
} }
@ -74,7 +77,7 @@ class IsChanged<T> {
* @param data 要设置的新数据值 * @param data 要设置的新数据值
* @return 设置前的旧数据值 * @return 设置前的旧数据值
*/ */
fun setAndGet(data: T): T { fun setAndGet(data: T): T? {
return atomicReferenceData.getAndSet(data) return atomicReferenceData.getAndSet(data)
} }
@ -86,7 +89,7 @@ class IsChanged<T> {
* @return 如果值发生变化返回 true否则返回 false * @return 如果值发生变化返回 true否则返回 false
*/ */
fun setAndChanged(data: T): Boolean { fun setAndChanged(data: T): Boolean {
var currentData: T var currentData: T?
do { do {
currentData = get() currentData = get()
// 如果新值与当前值相等,则认为没有变化,直接返回 false // 如果新值与当前值相等,则认为没有变化,直接返回 false

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BadGatewayException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 502 Bad Gateway 异常
*
* @param message 异常信息默认为 "Bad Gateway"
* @param cause 异常原因默认为 null
*/
class BadGatewayException(
override val message: String? = "Bad Gateway",
override val cause: Throwable? = null,
) : HttpStatusException(502, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BadRequestException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 400 Bad Request 异常
*
* @param message 异常信息默认为 "Bad Request"
* @param cause 异常原因默认为 null
*/
class BadRequestException(
override val message: String? = "Bad Request",
override val cause: Throwable? = null,
) : HttpStatusException(400, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ConflictException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 409 Conflict 异常
*
* @param message 异常信息默认为 "Conflict"
* @param cause 异常原因默认为 null
*/
class ConflictException(
override val message: String? = "Conflict",
override val cause: Throwable? = null,
) : HttpStatusException(409, message, cause)

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile EmptyJsonException.kt
* LastUpdate 2026-02-07 14:45:12
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class EmptyJsonException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ForbiddenException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 403 Forbidden 异常
*
* @param message 异常信息默认为 "Forbidden"
* @param cause 异常原因默认为 null
*/
class ForbiddenException(
override val message: String? = "Forbidden",
override val cause: Throwable? = null,
) : HttpStatusException(403, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile FoundException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 302 Found 异常
*
* @param message 异常信息默认为 "Found"
* @param cause 异常原因默认为 null
*/
class FoundException(
override val message: String? = "Found",
override val cause: Throwable? = null,
) : HttpStatusException(302, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile GatewayTimeoutException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 504 Gateway Timeout 异常
*
* @param message 异常信息默认为 "Gateway Timeout"
* @param cause 异常原因默认为 null
*/
class GatewayTimeoutException(
override val message: String? = "Gateway Timeout",
override val cause: Throwable? = null,
) : HttpStatusException(504, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile GoneException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 410 Gone 异常
*
* @param message 异常信息默认为 "Gone"
* @param cause 异常原因默认为 null
*/
class GoneException(
override val message: String? = "Gone",
override val cause: Throwable? = null,
) : HttpStatusException(410, message, cause)

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile HttpException.kt
* LastUpdate 2026-02-05 14:44:15
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
open class HttpException : MingLiUtilsBaseException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile HttpStatusException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 异常的基类继承自 [RuntimeException]
*
* @param statusCode HTTP 状态码
* @param message 异常信息默认为 null
* @param cause 异常原因默认为 null
*/
sealed class HttpStatusException(
open val statusCode: Int,
override val message: String? = null,
override val cause: Throwable? = null
) : MingLiUtilsBaseException(message, cause)

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile HttpUrlException.kt
* LastUpdate 2026-02-05 15:21:48
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
open class HttpUrlException : HttpException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile HttpVersionNotSupportedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 505 HTTP Version Not Supported 异常
*
* @param message 异常信息默认为 "HTTP Version Not Supported"
* @param cause 异常原因默认为 null
*/
class HttpVersionNotSupportedException(
override val message: String? = "HTTP Version Not Supported",
override val cause: Throwable? = null,
) : HttpStatusException(505, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile InternalServerErrorException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 500 Internal Server Error 异常
*
* @param message 异常信息默认为 "Internal Server Error"
* @param cause 异常原因默认为 null
*/
class InternalServerErrorException(
override val message: String? = "Internal Server Error",
override val cause: Throwable? = null,
) : HttpStatusException(500, message, cause)

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile InvalidJsonException.kt
* LastUpdate 2026-02-07 13:18:32
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class InvalidJsonException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,44 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JsonException.kt
* LastUpdate 2026-02-07 13:17:50
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 自定义异常类用于处理 JSON 相关操作中出现的错误
*
* 该类继承自 [RuntimeException]提供了三种构造函数以支持不同的异常场景
* 1. 仅包含错误信息的构造函数
* 2. 包含错误信息和原因Throwable的构造函数
* 3. 仅包含原因Throwable的构造函数
*/
open class JsonException : MingLiUtilsBaseException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JsonObjectCastException.kt
* LastUpdate 2026-02-07 15:11:42
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class JsonObjectCastException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JsonParserException.kt
* LastUpdate 2026-02-07 14:45:12
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class JsonParserException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JsonTypeException.kt
* LastUpdate 2026-02-07 13:28:02
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class JsonTypeException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile LengthRequiredException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 411 Length Required 异常
*
* @param message 异常信息默认为 "Length Required"
* @param cause 异常原因默认为 null
*/
class LengthRequiredException(
override val message: String? = "Length Required",
override val cause: Throwable? = null,
) : HttpStatusException(411, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile MethodNotAllowedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 405 Method Not Allowed 异常
*
* @param message 异常信息默认为 "Method Not Allowed"
* @param cause 异常原因默认为 null
*/
class MethodNotAllowedException(
override val message: String? = "Method Not Allowed",
override val cause: Throwable? = null,
) : HttpStatusException(405, message, cause)

View File

@ -1,37 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile MingLiUtilsBaseException.kt
* LastUpdate 2026-02-05 14:41:27
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
open class MingLiUtilsBaseException : RuntimeException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile MovedPermanentlyException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 301 Moved Permanently 异常
*
* @param message 异常信息默认为 "Moved Permanently"
* @param cause 异常原因默认为 null
*/
class MovedPermanentlyException(
override val message: String? = "Moved Permanently",
override val cause: Throwable? = null,
) : HttpStatusException(301, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile MultipleChoicesException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 300 Multiple Choices 异常
*
* @param message 异常信息默认为 "Multiple Choices"
* @param cause 异常原因默认为 null
*/
class MultipleChoicesException(
override val message: String? = "Multiple Choices",
override val cause: Throwable? = null,
) : HttpStatusException(300, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile NotAcceptableException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 406 Not Acceptable 异常
*
* @param message 异常信息默认为 "Not Acceptable"
* @param cause 异常原因默认为 null
*/
class NotAcceptableException(
override val message: String? = "Not Acceptable",
override val cause: Throwable? = null,
) : HttpStatusException(406, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile NotFoundException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 404 Not Found 异常
*
* @param message 异常信息默认为 "Not Found"
* @param cause 异常原因默认为 null
*/
class NotFoundException(
override val message: String? = "Not Found",
override val cause: Throwable? = null,
) : HttpStatusException(404, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile NotImplementedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 501 Not Implemented 异常
*
* @param message 异常信息默认为 "Not Implemented"
* @param cause 异常原因默认为 null
*/
class NotImplementedException(
override val message: String? = "Not Implemented",
override val cause: Throwable? = null,
) : HttpStatusException(501, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile NotModifiedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 304 Not Modified 异常
*
* @param message 异常信息默认为 "Not Modified"
* @param cause 异常原因默认为 null
*/
class NotModifiedException(
override val message: String? = "Not Modified",
override val cause: Throwable? = null,
) : HttpStatusException(304, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile PaymentRequiredException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 402 Payment Required 异常
*
* @param message 异常信息默认为 "Payment Required"
* @param cause 异常原因默认为 null
*/
class PaymentRequiredException(
override val message: String? = "Payment Required",
override val cause: Throwable? = null,
) : HttpStatusException(402, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile PreconditionFailedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 412 Precondition Failed 异常
*
* @param message 异常信息默认为 "Precondition Failed"
* @param cause 异常原因默认为 null
*/
class PreconditionFailedException(
override val message: String? = "Precondition Failed",
override val cause: Throwable? = null,
) : HttpStatusException(412, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ProxyAuthenticationRequiredException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 407 Proxy Authentication Required 异常
*
* @param message 异常信息默认为 "Proxy Authentication Required"
* @param cause 异常原因默认为 null
*/
class ProxyAuthenticationRequiredException(
override val message: String? = "Proxy Authentication Required",
override val cause: Throwable? = null,
) : HttpStatusException(407, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile RequestEntityTooLargeException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 413 Request Entity Too Large 异常
*
* @param message 异常信息默认为 "Request Entity Too Large"
* @param cause 异常原因默认为 null
*/
class RequestEntityTooLargeException(
override val message: String? = "Request Entity Too Large",
override val cause: Throwable? = null,
) : HttpStatusException(413, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile RequestTimeoutException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 408 Request Timeout 异常
*
* @param message 异常信息默认为 "Request Timeout"
* @param cause 异常原因默认为 null
*/
class RequestTimeoutException(
override val message: String? = "Request Timeout",
override val cause: Throwable? = null,
) : HttpStatusException(408, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile RequestUriTooLargeException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 414 Request URI Too Large 异常
*
* @param message 异常信息默认为 "Request URI Too Large"
* @param cause 异常原因默认为 null
*/
class RequestUriTooLargeException(
override val message: String? = "Request URI Too Large",
override val cause: Throwable? = null,
) : HttpStatusException(414, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile RequestedRangeNotSatisfiableException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 416 Requested Range Not Satisfiable 异常
*
* @param message 异常信息默认为 "Requested Range Not Satisfiable"
* @param cause 异常原因默认为 null
*/
class RequestedRangeNotSatisfiableException(
override val message: String? = "Requested Range Not Satisfiable",
override val cause: Throwable? = null,
) : HttpStatusException(416, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile SeeOtherException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 303 See Other 异常
*
* @param message 异常信息默认为 "See Other"
* @param cause 异常原因默认为 null
*/
class SeeOtherException(
override val message: String? = "See Other",
override val cause: Throwable? = null,
) : HttpStatusException(303, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ServiceUnavailableException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 503 Service Unavailable 异常
*
* @param message 异常信息默认为 "Service Unavailable"
* @param cause 异常原因默认为 null
*/
class ServiceUnavailableException(
override val message: String? = "Service Unavailable",
override val cause: Throwable? = null,
) : HttpStatusException(503, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile TemporaryRedirectException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 307 Temporary Redirect 异常
*
* @param message 异常信息默认为 "Temporary Redirect"
* @param cause 异常原因默认为 null
*/
class TemporaryRedirectException(
override val message: String? = "Temporary Redirect",
override val cause: Throwable? = null,
) : HttpStatusException(307, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UnauthorizedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 401 Unauthorized 异常
*
* @param message 异常信息默认为 "Unauthorized"
* @param cause 异常原因默认为 null
*/
class UnauthorizedException(
override val message: String? = "Unauthorized",
override val cause: Throwable? = null,
) : HttpStatusException(401, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UnsupportedMediaTypeException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 415 Unsupported Media Type 异常
*
* @param message 异常信息默认为 "Unsupported Media Type"
* @param cause 异常原因默认为 null
*/
class UnsupportedMediaTypeException(
override val message: String? = "Unsupported Media Type",
override val cause: Throwable? = null,
) : HttpStatusException(415, message, cause)

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UseProxyException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 305 Use Proxy 异常
*
* @param message 异常信息默认为 "Use Proxy"
* @param cause 异常原因默认为 null
*/
class UseProxyException(
override val message: String? = "Use Proxy",
override val cause: Throwable? = null,
) : HttpStatusException(305, message, cause)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile FileUtils.kt * CurrentFile FileUtils.kt
* LastUpdate 2026-01-28 10:49:14 * LastUpdate 2025-09-15 09:12:47
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("FileUtils") @file:JvmName("FileUtils")
@ -24,188 +24,195 @@
package com.mingliqiye.utils.file package com.mingliqiye.utils.file
import com.mingliqiye.utils.path.OsPath import com.mingliqiye.utils.path.OsPath
import java.io.File
import java.io.IOException import java.io.IOException
import java.nio.charset.Charset import java.nio.charset.Charset
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardOpenOption import java.nio.file.StandardOpenOption
/** /**
* 默认字符集 * 默认字符集
*/ */
var DEFAULT_CHARSET: Charset = StandardCharsets.UTF_8 var DEFAULT_CHARSET: Charset = StandardCharsets.UTF_8
// 读取文件内容为字符串
@Throws(IOException::class)
/**
* 读取文件内容为字符串使用默认字符集
*
* @return 文件内容的字符串表示
* @throws IOException 读取文件时发生错误
*/
fun String.readFileToString(): String {
return this.readFileToString(DEFAULT_CHARSET)
}
@Throws(IOException::class)
/** /**
* 读取文件内容为字符串 * 读取文件内容为字符串
* *
* @param charset 字符编码格式 * @param filePath 文件路径
* @return 文件内容字符串表示 * @return 文件内容字符串
* @throws IOException 读取文件时发生错误 * @throws IOException 读取文件时发生错误
*/ */
fun String.readFileToString(charset: Charset): String {
val path = OsPath.of(this) @Throws(IOException::class)
fun readFileToString(filePath: String): String {
return readFileToString(filePath, DEFAULT_CHARSET)
}
/**
* 读取文件内容为字符串
*
* @param filePath 文件路径
* @param charset 字符集
* @return 文件内容字符串
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readFileToString(filePath: String, charset: Charset): String {
val path = OsPath.of(filePath)
val bytes = Files.readAllBytes(path) val bytes = Files.readAllBytes(path)
return String(bytes, charset) return String(bytes, charset)
} }
// 将字符串写入文件
@Throws(IOException::class)
/**
* 将字符串写入文件使用默认字符集
*
* @param content 要写入的字符串内容
* @throws IOException 写入文件时发生错误
*/
fun String.writeStringToFile(content: String) {
this.writeStringToFile(content, DEFAULT_CHARSET)
}
@Throws(IOException::class)
/** /**
* 将字符串写入文件 * 将字符串写入文件
* *
* @param content 要写入的字符串内容 * @param filePath 文件路径
* @param charset 字符编码格式 * @param content 要写入的内容
* @throws IOException 写入文件时发生错误 * @throws IOException 写入文件时发生错误
*/ */
fun String.writeStringToFile(content: String, charset: Charset) { @Throws(IOException::class)
val path = Paths.get(this) fun writeStringToFile(filePath: String, content: String) {
writeStringToFile(filePath, content, DEFAULT_CHARSET)
}
/**
* 将字符串写入文件
*
* @param filePath 文件路径
* @param content 要写入的内容
* @param charset 字符集
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeStringToFile(filePath: String, content: String, charset: Charset) {
val path = Paths.get(filePath)
path.parent?.let { Files.createDirectories(it) } path.parent?.let { Files.createDirectories(it) }
Files.write(path, content.toByteArray(charset)) Files.write(path, content.toByteArray(charset))
} }
// 读取文件内容为字符串列表(按行分割)
@Throws(IOException::class)
/**
* 读取文件内容为字符串列表按行分割使用默认字符集
*
* @return 按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
fun String.readLines(): List<String> {
return this.readLines(DEFAULT_CHARSET)
}
@Throws(IOException::class)
/** /**
* 读取文件内容为字符串列表按行分割 * 读取文件内容为字符串列表按行分割
* *
* @param charset 字符编码格式 * @param filePath 文件路径
* @return 按行分割的字符串列表 * @return 文件内容按行分割的字符串列表
* @throws IOException 读取文件时发生错误 * @throws IOException 读取文件时发生错误
*/ */
fun String.readLines(charset: Charset): List<String> { @Throws(IOException::class)
val path = Paths.get(this) fun readLines(filePath: String): List<String> {
return readLines(filePath, DEFAULT_CHARSET)
}
/**
* 读取文件内容为字符串列表按行分割
*
* @param filePath 文件路径
* @param charset 字符集
* @return 文件内容按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
@Throws(IOException::class)
fun readLines(filePath: String, charset: Charset): List<String> {
val path = Paths.get(filePath)
return Files.readAllLines(path, charset) return Files.readAllLines(path, charset)
} }
// 将字符串列表写入文件(每行一个元素)
@Throws(IOException::class)
/**
* 将字符串列表写入文件每行一个元素使用默认字符集
*
* @param lines 要写入的字符串列表
* @throws IOException 写入文件时发生错误
*/
fun String.writeLines(lines: List<String>) {
this.writeLines(lines, DEFAULT_CHARSET)
}
@Throws(IOException::class)
/** /**
* 将字符串列表写入文件每行一个元素 * 将字符串列表写入文件每行一个元素
* *
* @param lines 要写入的字符串列表 * @param filePath 文件路径
* @param charset 字符编码格式 * @param lines 要写入的行内容列表
* @throws IOException 写入文件时发生错误 * @throws IOException 写入文件时发生错误
*/ */
fun String.writeLines(lines: List<String>, charset: Charset) { @Throws(IOException::class)
val path = Paths.get(this) fun writeLines(filePath: String, lines: List<String>) {
writeLines(filePath, lines, DEFAULT_CHARSET)
}
/**
* 将字符串列表写入文件每行一个元素
*
* @param filePath 文件路径
* @param lines 要写入的行内容列表
* @param charset 字符集
* @throws IOException 写入文件时发生错误
*/
@Throws(IOException::class)
fun writeLines(filePath: String, lines: List<String>, charset: Charset) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent) Files.createDirectories(path.parent)
Files.write(path, lines, charset) Files.write(path, lines, charset)
} }
// 复制文件
@Throws(IOException::class)
/** /**
* 复制文件到目标路径 * 复制文件
* *
* @param sourcePath 源文件路径
* @param targetPath 目标文件路径 * @param targetPath 目标文件路径
* @throws IOException 复制文件时发生错误 * @throws IOException 复制文件时发生错误
*/ */
fun String.copyFile(targetPath: String) { @Throws(IOException::class)
val source = Paths.get(this) fun copyFile(sourcePath: String, targetPath: String) {
val source = Paths.get(sourcePath)
val target = Paths.get(targetPath) val target = Paths.get(targetPath)
Files.createDirectories(target.parent) Files.createDirectories(target.parent)
Files.copy(source, target) Files.copy(source, target)
} }
// 删除文件
/** /**
* 删除文件 * 删除文件
* *
* @return 删除操作是否成功 * @param filePath 文件路径
* @return 如果文件删除成功返回true否则返回false
*/ */
fun String.deleteFile(): Boolean { fun deleteFile(filePath: String): Boolean {
return try { return try {
val path = Paths.get(this) val path = Paths.get(filePath)
Files.deleteIfExists(path) Files.deleteIfExists(path)
} catch (e: IOException) { } catch (e: IOException) {
false false
} }
} }
// 检查文件是否存在
/** /**
* 检查文件是否存在 * 检查文件是否存在
* *
* @return 文件是否存在 * @param filePath 文件路径
* @return 如果文件存在返回true否则返回false
*/ */
fun String.exists(): Boolean { fun exists(filePath: String): Boolean {
val path = Paths.get(this) val path = Paths.get(filePath)
return Files.exists(path) return Files.exists(path)
} }
// 获取文件大小
/** /**
* 获取文件大小 * 获取文件大小
* *
* @return 文件大小字节如果获取失败则返回-1 * @param filePath 文件路径
* @return 文件大小字节如果文件不存在返回-1
*/ */
fun String.getFileSize(): Long {
fun getFileSize(filePath: String): Long {
return try { return try {
val path = Paths.get(this) val path = Paths.get(filePath)
Files.size(path) Files.size(path)
} catch (e: IOException) { } catch (e: IOException) {
-1 -1
} }
} }
// 创建目录
/** /**
* 创建目录 * 创建目录
* *
* @return 创建操作是否成功 * @param dirPath 目录路径
* @return 如果目录创建成功返回true否则返回false
*/ */
fun String.createDirectory(): Boolean {
fun createDirectory(dirPath: String): Boolean {
return try { return try {
val path = Paths.get(this) val path = Paths.get(dirPath)
Files.createDirectories(path) Files.createDirectories(path)
true true
} catch (e: IOException) { } catch (e: IOException) {
@ -213,61 +220,97 @@ fun String.createDirectory(): Boolean {
} }
} }
// 读取文件内容为字节数组 /**
@Throws(IOException::class) * 获取文件扩展名
*
* @param fileName 文件名
* @return 文件扩展名不包含点号如果无扩展名返回空字符串
*/
fun getFileExtension(fileName: String): String {
if (fileName.isEmpty()) {
return ""
}
val lastDotIndex = fileName!!.lastIndexOf('.')
return if (lastDotIndex == -1 || lastDotIndex == fileName.length - 1) {
""
} else fileName.substring(lastDotIndex + 1)
}
/**
* 获取不带扩展名的文件名
*
* @param fileName 文件名
* @return 不带扩展名的文件名
*/
fun getFileNameWithoutExtension(fileName: String): String {
if (fileName.isEmpty()) {
return ""
}
val lastDotIndex = fileName!!.lastIndexOf('.')
return if (lastDotIndex == -1) {
fileName
} else fileName.substring(0, lastDotIndex)
}
/** /**
* 读取文件内容为字节数组 * 读取文件内容为字节数组
* *
* @return 文件内容的字节数组表示 * @param filePath 文件路径
* @return 文件内容的字节数组
* @throws IOException 读取文件时发生错误 * @throws IOException 读取文件时发生错误
*/ */
fun String.readByteArray(): ByteArray { @Throws(IOException::class)
val path = Paths.get(this) fun readFileToByteArray(filePath: String): ByteArray {
val path = Paths.get(filePath)
return Files.readAllBytes(path) return Files.readAllBytes(path)
} }
// 将字节数组写入文件
@Throws(IOException::class)
/** /**
* 将字节数组写入文件 * 将字节数组写入文件
* *
* @param data 要写入的字节数组 * @param filePath 文件路径
* @param data 要写入的字节数据
* @throws IOException 写入文件时发生错误 * @throws IOException 写入文件时发生错误
*/ */
fun String.writeByteArray(data: ByteArray) {
val path = Paths.get(this) @Throws(IOException::class)
fun writeByteArrayToFile(filePath: String, data: ByteArray) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent) Files.createDirectories(path.parent)
Files.write(path, data) Files.write(path, data)
} }
// 将字节数组追加到文件末尾
@Throws(IOException::class)
/** /**
* 将字节数组追加到文件末尾 * 将字节数组追加到文件末尾
* *
* @param data 要追加的字节数组 * @param filePath 文件路径
* @throws IOException 追加文件时发生错误 * @param data 要追加的字节数据
* @throws IOException 追加数据时发生错误
*/ */
fun String.appendByteArray(data: ByteArray) {
val path = Paths.get(this) @Throws(IOException::class)
fun appendByteArrayToFile(filePath: String, data: ByteArray) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent) Files.createDirectories(path.parent)
Files.write( Files.write(
path, data, StandardOpenOption.CREATE, StandardOpenOption.APPEND path, data, StandardOpenOption.CREATE, StandardOpenOption.APPEND
) )
} }
// 分块读取大文件为字节数组列表
@Throws(IOException::class)
/** /**
* 分块读取大文件为字节数组列表 * 分块读取大文件为字节数组列表
* *
* @param chunkSize 每个块的大小 * @param filePath 文件路径
* @return 字节数组列表 * @param chunkSize 每块大小字节
* @return 文件内容按指定大小分割的字节数组列表
* @throws IOException 读取文件时发生错误 * @throws IOException 读取文件时发生错误
*/ */
fun String.readByteArrayChunks(chunkSize: Int): List<ByteArray> {
@Throws(IOException::class)
fun readFileToByteArrayChunks(filePath: String, chunkSize: Int): List<ByteArray> {
val chunks = mutableListOf<ByteArray>() val chunks = mutableListOf<ByteArray>()
val path = Paths.get(this) val path = Paths.get(filePath)
Files.newInputStream(path).use { inputStream -> Files.newInputStream(path).use { inputStream ->
val buffer = ByteArray(chunkSize) val buffer = ByteArray(chunkSize)
@ -282,16 +325,17 @@ fun String.readByteArrayChunks(chunkSize: Int): List<ByteArray> {
return chunks return chunks
} }
// 将字节数组列表写入文件
@Throws(IOException::class)
/** /**
* 将字节数组列表写入文件 * 将字节数组列表写入文件
* *
* @param filePath 文件路径
* @param chunks 字节数组列表 * @param chunks 字节数组列表
* @throws IOException 写入文件时发生错误 * @throws IOException 写入文件时发生错误
*/ */
fun String.writeByteArrayChunks(chunks: List<ByteArray>) {
val path = Paths.get(this) @Throws(IOException::class)
fun writeByteArrayChunksToFile(filePath: String, chunks: List<ByteArray>) {
val path = Paths.get(filePath)
Files.createDirectories(path.parent) Files.createDirectories(path.parent)
Files.newOutputStream(path).use { outputStream -> Files.newOutputStream(path).use { outputStream ->
@ -300,445 +344,3 @@ fun String.writeByteArrayChunks(chunks: List<ByteArray>) {
} }
} }
} }
// 读取文件内容为字符串
@Throws(IOException::class)
/**
* 读取文件内容为字符串使用默认字符集
*
* @return 文件内容的字符串表示
* @throws IOException 读取文件时发生错误
*/
fun Path.readFileToString(): String {
return this.readFileToString(DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 读取文件内容为字符串
*
* @param charset 字符编码格式
* @return 文件内容的字符串表示
* @throws IOException 读取文件时发生错误
*/
fun Path.readFileToString(charset: Charset): String {
val bytes = Files.readAllBytes(this)
return String(bytes, charset)
}
// 将字符串写入文件
@Throws(IOException::class)
/**
* 将字符串写入文件使用默认字符集
*
* @param content 要写入的字符串内容
* @throws IOException 写入文件时发生错误
*/
fun Path.writeStringToFile(content: String) {
this.writeStringToFile(content, DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 将字符串写入文件
*
* @param content 要写入的字符串内容
* @param charset 字符编码格式
* @throws IOException 写入文件时发生错误
*/
fun Path.writeStringToFile(content: String, charset: Charset) {
this.parent?.let { Files.createDirectories(it) }
Files.write(this, content.toByteArray(charset))
}
// 读取文件内容为字符串列表
@Throws(IOException::class)
/**
* 读取文件内容为字符串列表使用默认字符集
*
* @return 按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
fun Path.readLines(): List<String> {
return this.readLines(DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 读取文件内容为字符串列表
*
* @param charset 字符编码格式
* @return 按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
fun Path.readLines(charset: Charset): List<String> {
return Files.readAllLines(this, charset)
}
// 将字符串列表写入文件
@Throws(IOException::class)
/**
* 将字符串列表写入文件使用默认字符集
*
* @param lines 要写入的字符串列表
* @throws IOException 写入文件时发生错误
*/
fun Path.writeLines(lines: List<String>) {
this.writeLines(lines, DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 将字符串列表写入文件
*
* @param lines 要写入的字符串列表
* @param charset 字符编码格式
* @throws IOException 写入文件时发生错误
*/
fun Path.writeLines(lines: List<String>, charset: Charset) {
Files.createDirectories(this.parent)
Files.write(this, lines, charset)
}
// 复制文件
@Throws(IOException::class)
/**
* 复制文件到目标路径
*
* @param target 目标文件路径
* @throws IOException 复制文件时发生错误
*/
fun Path.copyTo(target: Path) {
Files.createDirectories(target.parent)
Files.copy(this, target)
}
// 删除文件
/**
* 删除文件
*
* @return 删除操作是否成功
*/
fun Path.delete(): Boolean {
return try {
Files.deleteIfExists(this)
} catch (e: IOException) {
false
}
}
// 检查文件是否存在
/**
* 检查文件是否存在
*
* @return 文件是否存在
*/
fun Path.exists(): Boolean {
return Files.exists(this)
}
// 获取文件大小
/**
* 获取文件大小
*
* @return 文件大小字节如果获取失败则返回-1
*/
fun Path.getFileSize(): Long {
return try {
Files.size(this)
} catch (e: IOException) {
-1
}
}
// 读取文件内容为字节数组
@Throws(IOException::class)
/**
* 读取文件内容为字节数组
*
* @return 文件内容的字节数组表示
* @throws IOException 读取文件时发生错误
*/
fun Path.readByteArray(): ByteArray {
return Files.readAllBytes(this)
}
// 将字节数组写入文件
@Throws(IOException::class)
/**
* 将字节数组写入文件
*
* @param data 要写入的字节数组
* @throws IOException 写入文件时发生错误
*/
fun Path.writeByteArray(data: ByteArray) {
Files.createDirectories(this.parent)
Files.write(this, data)
}
// 将字节数组追加到文件末尾
@Throws(IOException::class)
/**
* 将字节数组追加到文件末尾
*
* @param data 要追加的字节数组
* @throws IOException 追加文件时发生错误
*/
fun Path.appendByteArray(data: ByteArray) {
Files.createDirectories(this.parent)
Files.write(this, data, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
}
// 分块读取大文件为字节数组列表
@Throws(IOException::class)
/**
* 分块读取大文件为字节数组列表
*
* @param chunkSize 每个块的大小
* @return 字节数组列表
* @throws IOException 读取文件时发生错误
*/
fun Path.readByteArrayChunks(chunkSize: Int): List<ByteArray> {
val chunks = mutableListOf<ByteArray>()
Files.newInputStream(this).use { inputStream ->
val buffer = ByteArray(chunkSize)
var bytesRead: Int
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
val chunk = ByteArray(bytesRead)
System.arraycopy(buffer, 0, chunk, 0, bytesRead)
chunks.add(chunk)
}
}
return chunks
}
// 将字节数组列表写入文件
@Throws(IOException::class)
/**
* 将字节数组列表写入文件
*
* @param chunks 字节数组列表
* @throws IOException 写入文件时发生错误
*/
fun Path.writeByteArrayChunks(chunks: List<ByteArray>) {
Files.createDirectories(this.parent)
Files.newOutputStream(this).use { outputStream ->
for (chunk in chunks) {
outputStream.write(chunk)
}
}
}
// 读取文件内容为字符串
@Throws(IOException::class)
/**
* 读取文件内容为字符串使用默认字符集
*
* @return 文件内容的字符串表示
* @throws IOException 读取文件时发生错误
*/
fun File.readFileToString(): String {
return this.readFileToString(DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 读取文件内容为字符串
*
* @param charset 字符编码格式
* @return 文件内容的字符串表示
* @throws IOException 读取文件时发生错误
*/
fun File.readFileToString(charset: Charset): String {
return String(this.readBytes(), charset)
}
// 将字符串写入文件
@Throws(IOException::class)
/**
* 将字符串写入文件使用默认字符集
*
* @param content 要写入的字符串内容
* @throws IOException 写入文件时发生错误
*/
fun File.writeStringToFile(content: String) {
this.writeStringToFile(content, DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 将字符串写入文件
*
* @param content 要写入的字符串内容
* @param charset 字符编码格式
* @throws IOException 写入文件时发生错误
*/
fun File.writeStringToFile(content: String, charset: Charset) {
this.parentFile?.mkdirs()
this.writeText(content, charset)
}
// 读取文件内容为字符串列表
@Throws(IOException::class)
/**
* 读取文件内容为字符串列表使用默认字符集
*
* @return 按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
fun File.readLines(): List<String> {
return this.readLines(DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 读取文件内容为字符串列表
*
* @param charset 字符编码格式
* @return 按行分割的字符串列表
* @throws IOException 读取文件时发生错误
*/
fun File.readLines(charset: Charset): List<String> {
return this.readLines(charset)
}
// 将字符串列表写入文件
@Throws(IOException::class)
/**
* 将字符串列表写入文件使用默认字符集
*
* @param lines 要写入的字符串列表
* @throws IOException 写入文件时发生错误
*/
fun File.writeLines(lines: List<String>) {
this.writeLines(lines, DEFAULT_CHARSET)
}
@Throws(IOException::class)
/**
* 将字符串列表写入文件
*
* @param lines 要写入的字符串列表
* @param charset 字符编码格式
* @throws IOException 写入文件时发生错误
*/
fun File.writeLines(lines: List<String>, charset: Charset) {
this.parentFile?.mkdirs()
this.writeLines(lines, charset)
}
// 复制文件
@Throws(IOException::class)
/**
* 复制文件到目标文件
*
* @param target 目标文件
* @throws IOException 复制文件时发生错误
*/
fun File.copyTo(target: File) {
target.parentFile?.mkdirs()
this.copyTo(target, overwrite = true)
}
// 获取文件大小
/**
* 获取文件大小
*
* @return 文件大小字节如果文件不存在则返回-1L
*/
fun File.getFileSize(): Long {
return if (this.exists()) this.length() else -1L
}
// 创建目录
/**
* 创建目录
*
* @return 创建操作是否成功
*/
fun File.createDirectory(): Boolean {
return this.mkdirs()
}
// 读取文件内容为字节数组
@Throws(IOException::class)
/**
* 读取文件内容为字节数组
*
* @return 文件内容的字节数组表示
* @throws IOException 读取文件时发生错误
*/
fun File.readByteArray(): ByteArray {
return this.readBytes()
}
// 将字节数组写入文件
@Throws(IOException::class)
/**
* 将字节数组写入文件
*
* @param data 要写入的字节数组
* @throws IOException 写入文件时发生错误
*/
fun File.writeByteArray(data: ByteArray) {
this.parentFile?.mkdirs()
this.writeBytes(data)
}
// 将字节数组追加到文件末尾
@Throws(IOException::class)
/**
* 将字节数组追加到文件末尾
*
* @param data 要追加的字节数组
* @throws IOException 追加文件时发生错误
*/
fun File.appendByteArray(data: ByteArray) {
this.parentFile?.mkdirs()
this.appendBytes(data)
}
// 分块读取大文件为字节数组列表
@Throws(IOException::class)
/**
* 分块读取大文件为字节数组列表
*
* @param chunkSize 每个块的大小
* @return 字节数组列表
* @throws IOException 读取文件时发生错误
*/
fun File.readByteArrayChunks(chunkSize: Int): List<ByteArray> {
val chunks = mutableListOf<ByteArray>()
this.inputStream().use { inputStream ->
val buffer = ByteArray(chunkSize)
var bytesRead: Int
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
val chunk = ByteArray(bytesRead)
System.arraycopy(buffer, 0, chunk, 0, bytesRead)
chunks.add(chunk)
}
}
return chunks
}
// 将字节数组列表写入文件
@Throws(IOException::class)
/**
* 将字节数组列表写入文件
*
* @param chunks 字节数组列表
* @throws IOException 写入文件时发生错误
*/
fun File.writeByteArrayChunks(chunks: List<ByteArray>) {
this.parentFile?.mkdirs()
this.outputStream().use { outputStream ->
for (chunk in chunks) {
outputStream.write(chunk)
}
}
}

View File

@ -1,81 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Debouncer.kt
* LastUpdate 2026-01-11 09:10:30
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.functions
import java.util.concurrent.*
/**
* 防抖器类用于实现防抖功能防止在短时间内重复执行相同任务
*
* @author MingLiPro
*/
class Debouncer(private val delay: Long, unit: TimeUnit) {
private val scheduler: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
private val delayedMap: ConcurrentHashMap<Any, Future<*>> = ConcurrentHashMap()
private val delayMillis: Long = unit.toMillis(delay)
/**
* 执行防抖操作如果在指定延迟时间内再次调用相同key的任务则取消之前的任务并重新计时
*
* @param key 任务的唯一标识符用于区分不同任务
* @param task 要执行的任务
*/
fun debounce(key: Any, task: Runnable) {
// 提交新任务并获取之前可能存在的任务
val prev = delayedMap.put(
key,
scheduler.schedule(
{
try {
task.run()
} finally {
// 任务执行完成后从映射中移除
delayedMap.remove(key)
}
},
delayMillis,
TimeUnit.MILLISECONDS
)
)
// 如果之前存在任务,则取消它
if (prev != null) {
prev.cancel(true)
}
}
/**
* 关闭防抖器取消所有待执行的任务并关闭调度器
*/
fun shutdown() {
// 先取消所有延迟任务
for (future in delayedMap.values) {
future.cancel(true)
}
delayedMap.clear()
// 再关闭调度器
scheduler.shutdownNow()
}
}

View File

@ -16,25 +16,68 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Functions.kt * CurrentFile Functions.kt
* LastUpdate 2026-02-05 11:20:59 * LastUpdate 2026-01-09 08:12:01
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("Functions")
package com.mingliqiye.utils.functions package com.mingliqiye.utils.functions
fun <T> T.with(function: Function): T = function.call().let { import java.util.concurrent.*
this
/**
* 防抖器类用于实现防抖功能防止在短时间内重复执行相同任务
*
* @author MingLiPro
*/
class Debouncer(private val delay: Long, unit: TimeUnit) {
private val scheduler: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
private val delayedMap: ConcurrentHashMap<Any, Future<*>> = ConcurrentHashMap()
private val delayMillis: Long = unit.toMillis(delay)
/**
* 执行防抖操作如果在指定延迟时间内再次调用相同key的任务则取消之前的任务并重新计时
*
* @param key 任务的唯一标识符用于区分不同任务
* @param task 要执行的任务
*/
fun debounce(key: Any, task: Runnable) {
// 提交新任务并获取之前可能存在的任务
val prev = delayedMap.put(
key,
scheduler.schedule(
{
try {
task.run()
} finally {
// 任务执行完成后从映射中移除
delayedMap.remove(key)
}
},
delayMillis,
TimeUnit.MILLISECONDS
)
)
// 如果之前存在任务,则取消它
if (prev != null) {
prev.cancel(true)
}
} }
fun <T> T.with(function: P1Function<T>): T = function.call(this).let { /**
this * 关闭防抖器取消所有待执行的任务并关闭调度器
*/
fun shutdown() {
// 先取消所有延迟任务
for (future in delayedMap.values) {
future.cancel(true)
} }
delayedMap.clear()
@FunctionalInterface // 再关闭调度器
fun interface Function { scheduler.shutdownNow()
fun call() }
} }
@FunctionalInterface @FunctionalInterface
@ -141,597 +184,3 @@ fun interface P10Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9> {
fun interface P10RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, R> { fun interface P10RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, R> {
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R
} }
@FunctionalInterface
fun interface P11Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10> {
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10)
}
@FunctionalInterface
fun interface P11RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, R> {
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R
}
@FunctionalInterface
fun interface P12Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11> {
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11)
}
@FunctionalInterface
fun interface P12RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, R> {
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R
}
@FunctionalInterface
fun interface P13Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> {
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12)
}
@FunctionalInterface
fun interface P13RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12
): R
}
@FunctionalInterface
fun interface P14Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13
)
}
@FunctionalInterface
fun interface P14RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13
): R
}
@FunctionalInterface
fun interface P15Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14
)
}
@FunctionalInterface
fun interface P15RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14
): R
}
@FunctionalInterface
fun interface P16Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15
)
}
@FunctionalInterface
fun interface P16RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15
): R
}
@FunctionalInterface
fun interface P17Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16
)
}
@FunctionalInterface
fun interface P17RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16
): R
}
@FunctionalInterface
fun interface P18Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17
)
}
@FunctionalInterface
fun interface P18RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17
): R
}
@FunctionalInterface
fun interface P19Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18
)
}
@FunctionalInterface
fun interface P19RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18
): R
}
@FunctionalInterface
fun interface P20Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19
)
}
@FunctionalInterface
fun interface P20RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19
): R
}
@FunctionalInterface
fun interface P21Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20
)
}
@FunctionalInterface
fun interface P21RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20
): R
}
@FunctionalInterface
fun interface P22Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20,
p21: P21
)
}
@FunctionalInterface
fun interface P22RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20,
p21: P21
): R
}
@FunctionalInterface
fun interface P23Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20,
p21: P21,
p22: P22
)
}
@FunctionalInterface
fun interface P23RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20,
p21: P21,
p22: P22
): R
}
@FunctionalInterface
fun interface P24Function<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20,
p21: P21,
p22: P22,
p23: P23
)
}
@FunctionalInterface
fun interface P24RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, R> {
fun call(
p: P,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
p7: P7,
p8: P8,
p9: P9,
p10: P10,
p11: P11,
p12: P12,
p13: P13,
p14: P14,
p15: P15,
p16: P16,
p17: P17,
p18: P18,
p19: P19,
p20: P20,
p21: P21,
p22: P22,
p23: P23
): R
}

View File

@ -1,272 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Pipeline.kt
* LastUpdate 2026-02-05 15:22:21
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.functions
import com.mingliqiye.utils.require.Require
import java.util.*
/**
* 流水线操作类提供链式调用的操作方式来处理数据转换和操作
* @param T 泛型类型表示流水线中处理的数据类型
*/
class Pipeline<T>(private val value: T) {
/**
* 对当前值进行转换操作并返回新的Pipeline实例
* @param transformer 转换函数接收当前值并返回转换后的结果
* @return 包含转换后结果的新Pipeline实例
*/
fun <R> transform(transformer: P1RFunction<T, R>): Pipeline<R> = Pipeline(transformer.call(value))
/**
* 对当前值进行转换操作功能与transform相同提供不同的方法名选择
* @param transformer 转换函数接收当前值并返回转换后的结果
* @return 包含转换后结果的新Pipeline实例
*/
fun <R> then(transformer: P1RFunction<T, R>): Pipeline<R> = transform(transformer)
/**
* 消费当前值但不改变流水线状态用于执行副作用操作
* @param consumer 消费函数接收当前值进行消费操作
* @return 当前Pipeline实例支持链式调用
*/
fun consume(consumer: P1Function<T>): Pipeline<T> {
consumer.call(value)
return this
}
/**
* 判断当前值是否为null
* @return true表示当前值为nullfalse表示不为null
*/
fun isNull(): Boolean = (value == null)
/**
* 判断当前值是否不为null
* @return true表示当前值不为nullfalse表示为null
*/
fun isNotNull(): Boolean = (value != null)
/**
* 根据条件过滤当前值如果条件满足则保持原值否则设置为null
* @param predicate 过滤条件函数接收当前值并返回布尔值
* @return 包含过滤后结果的Pipeline实例
*/
fun filter(predicate: P1RFunction<T, Boolean>): Pipeline<T?> =
if (predicate.call(value)) Pipeline(value) else Pipeline(null)
/**
* 获取当前流水线中的值
* @return 当前流水线中存储的值
*/
fun getValue(): T = value
/**
* 安全地转换当前值允许转换结果为null
* @param transformer 转换函数可能返回null
* @return 包含转换后结果可能为null的Pipeline实例
*/
fun <R> safeTransform(transformer: P1RFunction<T, R?>): Pipeline<R?> = Pipeline(transformer.call(value))
/**
* 将当前值映射为另一个Pipeline实例
* @param mapper 映射函数接收当前值并返回Pipeline实例
* @return 映射后的Pipeline实例
*/
fun <R> flatMap(mapper: P1RFunction<T, Pipeline<R>>): Pipeline<R> = mapper.call(value)
/**
* 将当前值映射为非null结果如果当前值为null则直接返回null
* @param mapper 映射函数可能返回null
* @return 包含映射后结果的Pipeline实例
*/
fun <R> mapNotNull(mapper: P1RFunction<T, R?>): Pipeline<out R?> =
if (value != null) Pipeline(mapper.call(value)!!) else Pipeline(null)
/**
* 将当前值强制转换为指定类型
* @param type 目标类型Class对象
* @return 包含转换后类型的Pipeline实例
* @throws ClassCastException 当类型转换失败时抛出异常
*/
@Throws(ClassCastException::class)
fun <E> cast(type: Class<E>): Pipeline<E> = Pipeline(value as E)
/**
* 根据条件判断是否保留当前值条件满足时保留否则返回null
* @param predicate 条件判断函数
* @return 包含条件判断结果的Pipeline实例
*/
fun takeIf(predicate: P1RFunction<T, Boolean>): Pipeline<T?> = Pipeline(if (predicate.call(value)) value else null)
/**
* 根据条件判断是否保留当前值条件不满足时保留否则返回null
* @param predicate 条件判断函数
* @return 包含条件判断结果的Pipeline实例
*/
fun takeUnless(predicate: P1RFunction<T, Boolean>): Pipeline<T?> =
Pipeline(if (!predicate.call(value)) value else null)
/**
* 在当前值上执行指定操作并返回操作结果
* @param block 执行函数接收当前值并返回结果
* @return 包含执行结果的Pipeline实例
*/
fun <R> let(block: P1RFunction<T, R>): Pipeline<R> = Pipeline(block.call(value))
/**
* 如果当前值不为null则返回自身否则返回默认值的Pipeline实例
* @param defaultValue 默认值
* @return 当前值或默认值的Pipeline实例
*/
fun orElse(defaultValue: T): Pipeline<T> = if (value != null) this else Pipeline(defaultValue)
/**
* 如果当前值不为null则返回自身否则通过供应商函数获取默认值
* @param supplier 默认值供应商函数
* @return 当前值或供应商提供的值的Pipeline实例
*/
fun orElseGet(supplier: RFunction<T>): Pipeline<T> = if (value != null) this else Pipeline(supplier.call())
/**
* 验证当前值是否等于指定值如果不相等则抛出异常
* @param any 比较的目标值
* @param message 错误消息
* @param exception 异常类型默认为IllegalArgumentException
* @return 当前Pipeline实例
*/
fun require(
any: Any, message: String, exception: Class<out Exception> = IllegalArgumentException::class.java
): Pipeline<T> {
Require.require(Objects.equals(any, value), message, exception)
return this
}
/**
* 验证当前值是否等于指定值如果不相等则抛出IllegalArgumentException异常
* @param any 比较的目标值
* @param message 错误消息
* @return 当前Pipeline实例
*/
fun require(
any: Any, message: String
): Pipeline<T> {
Require.RequireLayz.require(any == value, message)
return this
}
/**
* 使用P1RFunction验证当前值是否满足条件不满足则抛出异常
* @param must 验证条件函数
* @param message 错误消息
* @param exception 异常类型默认为IllegalArgumentException
* @return 当前Pipeline实例
*/
fun require(
must: P1RFunction<T, Boolean>,
message: String,
exception: Class<out Throwable> = IllegalArgumentException::class.java
): Pipeline<T> {
Require.require(must.call(value), message, exception)
return this
}
/**
* 使用P1RFunction验证当前值是否满足条件不满足则抛出IllegalArgumentException异常
* @param must 验证条件函数
* @param message 错误消息
* @return 当前Pipeline实例
*/
fun require(
must: P1RFunction<T, Boolean>, message: String
): Pipeline<T> {
Require.require(must.call(value), message, IllegalArgumentException::class.java)
return this
}
/**
* 对当前值执行指定操作但不改变流水线状态
* @param block 执行函数接收当前值
* @return 当前Pipeline实例
*/
fun also(block: P1Function<T>): Pipeline<T> {
block.call(value)
return this
}
/**
* 验证当前值是否满足指定条件不满足则抛出IllegalArgumentException异常
* @param predicate 验证条件函数
* @param lazyMessage 延迟错误消息生成函数默认返回"Requirement failed"
* @return 当前Pipeline实例
*/
fun require(
predicate: P1RFunction<T, Boolean>,
lazyMessage: P1RFunction<T, Any> = P1RFunction { "Requirement failed" }
): Pipeline<T> {
if (!predicate.call(value)) {
throw IllegalArgumentException(lazyMessage.call(value).toString())
}
return this
}
/**
* 使用比较器比较当前值与另一个值
* @param other 另一个比较值
* @param comparator 比较器
* @return 比较结果负数表示小于0表示相等正数表示大于
*/
fun compareWith(other: T, comparator: Comparator<in T>): Int = comparator.compare(value, other)
/**
* 使用选择器将当前值转换为可比较类型后与另一个值比较
* @param other 另一个比较值
* @param selector 选择器函数将当前值转换为可比较类型
* @return 比较结果
*/
fun <R : Comparable<R>> compareTo(other: R, selector: P1RFunction<T, R>): Int =
selector.call(value).compareTo(other)
companion object {
/**
* 创建包含指定值的Pipeline实例
* @param value 要包装的值
* @return 新的Pipeline实例
*/
@JvmStatic
fun <T> of(value: T): Pipeline<T> = Pipeline(value)
/**
* 通过供应商函数创建Pipeline实例
* @param transformer 值供应商函数
* @return 新的Pipeline实例
*/
@JvmStatic
fun <T> of(transformer: RFunction<T>): Pipeline<T> = Pipeline(transformer.call())
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile HashUtils.kt * CurrentFile HashUtils.kt
* LastUpdate 2026-01-11 09:09:52 * LastUpdate 2025-09-19 20:24:33
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("HashUtils") @file:JvmName("HashUtils")
@ -24,9 +24,9 @@
package com.mingliqiye.utils.hash package com.mingliqiye.utils.hash
import com.mingliqiye.utils.base.BASE16
import com.mingliqiye.utils.bcrypt.checkpw import com.mingliqiye.utils.bcrypt.checkpw
import com.mingliqiye.utils.bcrypt.hashpw import com.mingliqiye.utils.bcrypt.hashpw
import com.mingliqiye.utils.bytes.bytesToHex
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.IOException import java.io.IOException
@ -64,6 +64,16 @@ fun calculateFileHash(file: File, algorithm: String): String {
return bytesToHex(digest.digest()) return bytesToHex(digest.digest())
} }
/**
* 将字节数组转换为十六进制字符串表示
*
* @param bytes 输入的字节数组
* @return 对应的十六进制字符串
*/
private fun bytesToHex(bytes: ByteArray): String {
return BASE16.encode(bytes)
}
/** /**
* 使用 BCrypt 算法对字符串进行加密 * 使用 BCrypt 算法对字符串进行加密
* *

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,260 +16,48 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Response.kt * CurrentFile Response.kt
* LastUpdate 2026-02-07 22:18:42 * LastUpdate 2025-09-15 09:04:05
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.http package com.mingliqiye.utils.http
import com.mingliqiye.utils.annotation.DateTimeJsonFormat
import com.mingliqiye.utils.json.converters.DateTimeJsonConverter
import com.mingliqiye.utils.json.converters.base.AnnotationGetter
import com.mingliqiye.utils.time.DateTime import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.Formatter
/**
* HTTP响应数据类
* 封装了时间消息数据和状态码等响应信息
*
* @param T 响应数据的类型
* @property time 响应时间
* @property message 响应消息
* @property data 响应数据
* @property statusCode 状态码
*/
data class Response<T>( data class Response<T>(
private var time: DateTime, val time: String,
private var message: String, var message: String,
private var data: T?, var data: T?,
private var statusCode: Int, var statusCode: Int
) { ) {
private var timeFormat: DateTimeJsonFormat = DateTimeJsonFormat()
companion object { companion object {
/**
* 创建一个成功的响应对象仅包含消息
*
* @param message 响应消息
* @return Response<Any> 成功的响应对象
*/
@JvmStatic @JvmStatic
fun ok(message: String) = Response( fun <T> ok(data: T): Response<T?> {
time = DateTime.now(), return Response(DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7), "操作成功", data, 200)
message = message,
data = null,
statusCode = 200
)
/**
* 创建一个成功的响应对象仅包含数据
*
* @param T 响应数据的类型
* @param data 响应数据
* @return Response<T> 成功的响应对象
*/
@JvmStatic
fun <T> okData(data: T) = Response(
time = DateTime.now(),
message = "操作成功",
data = data,
statusCode = 200
)
/**
* 创建一个成功的响应对象包含数据和消息
*
* @param T 响应数据的类型
* @param data 响应数据
* @param message 响应消息
* @return Response<T> 成功的响应对象
*/
@JvmStatic
fun <T> okData(data: T, message: String) = Response(
time = DateTime.now(),
message = message,
data = data,
statusCode = 200
)
/**
* 创建一个指定状态码的响应对象仅包含状态码
*
* @param statusCode 状态码
* @return Response<Any> 指定状态码的响应对象
*/
@JvmStatic
fun code(statusCode: Int) = Response(
time = DateTime.now(),
message = "操作成功",
data = null,
statusCode = statusCode
)
/**
* 创建一个指定状态码的响应对象包含状态码和消息
*
* @param statusCode 状态码
* @param message 响应消息
* @return Response<Any> 指定状态码的响应对象
*/
@JvmStatic
fun code(statusCode: Int, message: String) = Response(
time = DateTime.now(),
message = message,
data = null,
statusCode = statusCode
)
} }
/** @JvmStatic
* 默认构造函数创建一个默认的成功响应对象 fun <T> ok(message: String): Response<T?> {
*/ return Response(DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7), message, null, 200)
constructor() : this( }
time = DateTime.now(), message = "操作成功", statusCode = 200, data = null
)
/**
* 获取格式化后的时间字符串
*
* @return 格式化后的时间字符串使用 [DateTimeJsonConverter] [timeFormat] 注解进行转换
*/
fun getTime(): String =
DateTimeJsonConverter.getJsonConverter().convert(time, AnnotationGetter.oneGetter(timeFormat))!!
/**
* 设置时间字段的值
*
* @param dateTime 格式化后的时间字符串将被反序列化为内部时间对象
* @return 返回当前对象实例支持链式调用
*/
fun setTime(dateTime: String): Response<T> {
// 使用 DateTimeJsonConverter 将输入的字符串反序列化为时间对象,并更新内部 time 字段
time = DateTimeJsonConverter.getJsonConverter().deConvert(dateTime, AnnotationGetter.oneGetter(timeFormat))!!
return this
} }
/**
* 获取响应消息
*
* @return String 响应消息
*/
fun getMessage(): String = message
/**
* 设置响应消息
*
* @param message 响应消息
* @return Response<T> 当前响应对象用于链式调用
*/
fun setMessage(message: String): Response<T> { fun setMessage(message: String): Response<T> {
this.message = message this.message = message
return this return this
} }
/** fun setData(data: T): Response<T?> {
* 获取响应数据
*
* @return T? 响应数据可能为空
*/
fun getData(): T? = data
/**
* 获取非空数据对象
*
* 此方法强制解包data属性如果data为null则会抛出NullPointerException异常
*
* @param T 泛型类型参数表示返回的数据类型
* @return 返回非空的数据对象类型为T
* @throws NullPointerException 当data属性为null时抛出此异常
*/
@Throws(NullPointerException::class)
fun notNullData(): T {
return data ?: throw NullPointerException("at Response.notNullData() because data is null")
}
/**
* 设置响应数据
*
* @param D 数据类型
* @param data 响应数据
* @return Response<D> 当前响应对象用于链式调用
*
*/
fun setData(data: T): Response<T> {
this.data = data this.data = data
return this return ok(this.data)
.setMessage(this.message)
.setStatusCode(this.statusCode)
} }
/**
* 创建一个新的Response对象使用指定的时间
*
* @param time 新的响应时间
* @return Response<T> 新的响应对象
*/
fun withTime(time: DateTime): Response<T> =
if (this.time == time) this else Response(time, message, data, statusCode)
/**
* 创建一个新的Response对象使用指定的数据
*
* @param D 新的数据类型
* @param data 新的响应数据
* @return Response<D> 新的响应对象
*/
fun <D> withData(data: D): Response<D> =
Response(this.time, this.message, data, this.statusCode)
/**
* 创建一个新的Response对象使用指定的消息
*
* @param message 新的响应消息
* @return Response<T> 新的响应对象
*/
fun withMessage(message: String): Response<T> =
if (this.message == message) this else Response(time, message, data, statusCode)
/**
* 创建一个新的Response对象使用指定的状态码
*
* @param statusCode 新的状态码
* @return Response<T> 新的响应对象
*/
fun withStatusCode(statusCode: Int): Response<T> =
if (this.statusCode == statusCode) this else Response(time, message, data, statusCode)
/**
* 获取状态码
*
* @return Int 状态码
*/
fun getStatusCode(): Int = statusCode
/**
* 设置状态码
*
* @param statusCode 状态码
* @return Response<T> 当前响应对象用于链式调用
*/
fun setStatusCode(statusCode: Int): Response<T> { fun setStatusCode(statusCode: Int): Response<T> {
this.statusCode = statusCode this.statusCode = statusCode
return this return this
} }
fun writeTimeFormat(timeFormat: DateTimeJsonFormat): Response<T> {
this.timeFormat = timeFormat
return this
}
fun readTimeFormat(): DateTimeJsonFormat = timeFormat
/**
* 返回响应对象的字符串表示
*/
override fun toString(): String =
"Response(time=${getTime()}, message=${getMessage()}, data:[${data?.javaClass?.simpleName}]=${getData()}, statusCode=${getStatusCode()})"
} }

View File

@ -1,964 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile I18N.kt
* LastUpdate 2026-02-05 22:39:07
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.i18n
import com.fasterxml.jackson.databind.ObjectMapper
import org.slf4j.Logger
object I18N {
@JvmStatic
private var _Internationalization: Internationalization = Internationalization(
clazz = I18N::class.java,
objectMapper = ObjectMapper(),
isloadSlef = true
)
fun setInternationalization(value: Internationalization) {
this._Internationalization = value
}
fun getInternationalization() = _Internationalization
@JvmStatic
fun getString(string: String, vararg any: Any): String = _Internationalization.getString(string, *any)
@JvmStatic
fun getString(string: String): String = _Internationalization.getString(string)
@JvmStatic
fun getKeyString(key: String): String = _Internationalization.getKeyString(key)
fun Logger.infoTranslater(string: String, vararg any: Any) = this.info(getString(string, *any))
fun Logger.warnTranslater(string: String, vararg any: Any) = this.warn(getString(string, *any))
fun Logger.debugTranslater(string: String, vararg any: Any) = this.debug(getString(string, *any))
fun Logger.traceTranslater(string: String, vararg any: Any) = this.trace(getString(string, *any))
// 0 个参数
fun Logger.errorTranslater(string: String, any1: Any) {
this.error(getString(string))
}
fun Logger.errorTranslater(string: String) {
this.error(getString(string))
}
// 2 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any) {
this.error(getString(string, any1, any2))
}
// 3 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any, any3: Any) {
this.error(getString(string, any1, any2, any3))
}
// 4 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
) {
this.error(getString(string, any1, any2, any3, any4))
}
// 5 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5))
}
// 6 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6))
}
// 7 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7))
}
// 8 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8))
}
// 9 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9))
}
// 10 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10))
}
// 11 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11))
}
// 12 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any, any12: Any,
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12)
)
}
// 13 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any, any12: Any, any13: Any,
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13),
)
}
// 14 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any, any12: Any, any13: Any, any14: Any,
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14
)
)
}
// 15 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14, any15
)
)
}
// 16 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16
)
)
}
// 17 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17
)
)
}
// 18 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18
)
)
}
// 19 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19
)
)
}
// 20 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
any20: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19,
any20
)
)
}
fun Logger.errorTranslater(string: String, throwable: Throwable) {
this.error(getString(string), throwable)
}
// 1 个参数
fun Logger.errorTranslater(string: String, any1: Any, throwable: Throwable) {
this.error(getString(string, any1), throwable)
}
// 2 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any, throwable: Throwable) {
this.error(getString(string, any1, any2), throwable)
}
// 3 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any, any3: Any, throwable: Throwable) {
this.error(getString(string, any1, any2, any3), throwable)
}
// 4 个参数
fun Logger.errorTranslater(
string: String, any1: Any, any2: Any, any3: Any, any4: Any, throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4), throwable)
}
// 5 个参数
fun Logger.errorTranslater(
string: String, any1: Any, any2: Any, any3: Any, any4: Any, any5: Any, throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5), throwable)
}
// 6 个参数
fun Logger.errorTranslater(
string: String, any1: Any, any2: Any, any3: Any, any4: Any, any5: Any, any6: Any, throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6), throwable)
}
// 7 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7), throwable)
}
// 8 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8), throwable)
}
// 9 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9), throwable)
}
// 10 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10), throwable)
}
// 11 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11), throwable)
}
// 12 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
throwable: Throwable
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12), throwable
)
}
// 13 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
throwable: Throwable
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13),
throwable
)
}
// 14 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
throwable: Throwable
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14
), throwable
)
}
// 15 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
throwable: Throwable
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14, any15
), throwable
)
}
// 16 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16
), throwable
)
}
// 17 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17
), throwable
)
}
// 18 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18
), throwable
)
}
// 19 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19
), throwable
)
}
// 20 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
any20: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19,
any20
), throwable
)
}
}

View File

@ -1,144 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Internationalization.kt
* LastUpdate 2026-02-06 08:47:26
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.i18n
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import org.slf4j.Logger
import java.net.URL
import java.util.*
class Internationalization {
var clazz: Class<*>
var objectMapper: ObjectMapper
var locale: Locale
var backLocale: Locale
val langPath: String
val thisName: String
val thisBackName: String
private var log: Logger = MingLiLoggerFactory.getLogger<Internationalization>()
constructor(
clazz: Class<*>,
objectMapper: ObjectMapper,
locale: Locale = Locale.getDefault(),
backLocale: Locale = Locale.US,
langPath: String = "/lang",
isloadSlef: Boolean = false
) {
this.clazz = clazz
this.objectMapper = objectMapper
this.locale = locale
this.backLocale = backLocale
this.langPath = langPath
thisName = getLanguageName(locale)
thisBackName = getLanguageName(backLocale)
readJson("/assets/mingli-utils/lang/${thisName}.json", Internationalization::class.java, thisName)
if (!isloadSlef) {
if (!readJson(fileName = "$langPath/${thisName}.json", lang = thisName)) {
log.warn(getString("com.mingliqiye.utils.i18n.readjson.error", "$langPath/${thisName}.json"))
}
}
if (thisName != thisBackName) {
readJson("/assets/mingli-utils/lang/${thisBackName}.json", Internationalization::class.java, thisBackName)
if (!isloadSlef) {
if (!readJson(fileName = "$langPath/${thisBackName}.json", lang = thisBackName)) {
log.warn(getString("com.mingliqiye.utils.i18n.readjson.error", "$langPath/${thisBackName}.json"))
}
}
}
}
fun getString(string: String, vararg any: Any): String {
return getString(string).format(*any)
}
fun getString(string: String): String {
return getKeyString(string)
}
fun getKeyString(key: String): String {
val s = localesData[thisName]?.get(key) ?: localesData[thisBackName]?.get(key)
if (s == null) {
return key
}
return s
}
fun getLanguageName(locale: Locale): String =
if (locale.country == null || locale.language == null) locale.country + locale.language else locale.language + '_' + locale.country
constructor(
clazz: Class<*>,
objectMapper: ObjectMapper,
) : this(
locale = Locale.getDefault(), clazz = clazz, objectMapper = objectMapper
)
constructor(
clazz: Class<*>, objectMapper: ObjectMapper, langPath: String = "/lang"
) : this(
locale = Locale.getDefault(), clazz = clazz, langPath = langPath, objectMapper = objectMapper
)
val localesData: MutableMap<String, MutableMap<String, String>> = mutableMapOf()
fun getlangFile(
clazzd: Class<*>, fileName: String
): URL? {
return clazzd.getResource(fileName)
}
fun readJson(
fileName: String, clazzd: Class<*> = clazz, lang: String
): Boolean {
val byteArray: ByteArray? = getlangFile(clazzd, fileName)?.openStream()?.use { it.readBytes() }
if (byteArray == null) return false
val node: JsonNode = objectMapper.readTree(byteArray)
if (node.isArray) return false
if (node.isEmpty) return false
var m = localesData[lang]
if (m == null) {
m = mutableMapOf()
localesData[lang] = m
}
readJsonNode(node, "", m)
return true
}
fun readJsonNode(node: JsonNode, path: String, map: MutableMap<String, String>) {
val fields = node.properties().iterator()
while (fields.hasNext()) {
val (k, v) = fields.next()
val pathName = if (path.isEmpty()) path + k else "$path.$k"
if (v.isTextual) {
map[pathName] = v.asText()
} else if (v.isObject) {
readJsonNode(v, pathName, map)
}
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,96 +16,37 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile IO.kt * CurrentFile IO.kt
* LastUpdate 2026-02-06 13:21:33 * LastUpdate 2025-09-20 16:03:14
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.io package com.mingliqiye.utils.io
import com.mingliqiye.utils.array.toHexString
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import com.mingliqiye.utils.string.join
import org.slf4j.Logger
import java.io.OutputStream
import java.io.PrintStream
fun Any?.println() {
/** IO.println(this)
* IO工具类提供打印功能和系统输出流重定向到日志的功能
*/
object IO {
@JvmStatic
fun ByteArray.println(): ByteArray {
this.toHexString().chunked(2).println()
return this
} }
@JvmStatic
fun <T> List<T>.println(): List<T> {
println("{" + ",".join(this) + "}")
return this
}
@JvmStatic class IO {
fun <T> Array<T>.println(): Array<T> { companion object {
println("{" + ",".join(this) + "}")
return this
}
@JvmStatic
fun <T> T.println(): T {
println(this)
return this
}
@JvmStatic
var originalOut: PrintStream = System.out
@JvmStatic
var originalErr: PrintStream = System.err
@JvmStatic
val outLog: Logger = MingLiLoggerFactory.getLogger("out")
@JvmStatic
val errLog: Logger = MingLiLoggerFactory.getLogger("err")
/**
* 打印多个参数使用空格分隔
* @param args 要打印的参数数组
*/
@JvmStatic @JvmStatic
fun print(vararg args: Any?) { fun print(vararg args: Any?) {
printA(" ", *args) printA(" ", *args)
} }
/**
* 打印多个参数并换行使用空格分隔
* @param args 要打印的参数数组
*/
@JvmStatic @JvmStatic
fun println(vararg args: Any?) { fun println(vararg args: Any?) {
printlnA(" ", *args) printlnA(" ", *args)
} }
/**
* 打印多个参数并换行指定分隔符
* @param sp 分隔符
* @param args 要打印的参数数组
*/
@JvmStatic @JvmStatic
fun printlnA(sp: String, vararg args: Any?) { fun printlnA(sp: String, vararg args: Any?) {
printA(" ", *args) printA(" ", *args)
kotlin.io.println() kotlin.io.println()
} }
/**
* 打印多个参数指定分隔符
* @param sp 分隔符默认为空字符串
* @param args 要打印的参数数组
*/
@JvmStatic @JvmStatic
fun printA(sp: String = "", vararg args: Any?) { fun printA(sp: String = "", vararg args: Any?) {
if (args.isEmpty()) { if (args.isEmpty()) {
@ -118,122 +59,5 @@ object IO {
} }
kotlin.io.print(sb) kotlin.io.print(sb)
} }
@JvmStatic
/**
* 重定向 System.out INFO 级别日志
*/
fun redirectOutToInfo() {
val outLogger = PrintStream(object : OutputStream() {
private val buffer = StringBuilder()
override fun write(b: Int) {
if (b == '\n'.code) {
flushBuffer()
} else {
buffer.append(b.toChar())
}
}
override fun write(b: ByteArray, off: Int, len: Int) {
val str = String(b, off, len)
if (str.contains("\n")) {
val lines = str.split("\n")
lines.forEachIndexed { index, line ->
if (index == lines.size - 1 && !str.endsWith("\n")) {
buffer.append(line)
} else {
buffer.append(line)
flushBuffer()
}
}
} else {
buffer.append(str)
}
}
private fun flushBuffer() {
val message = buffer.toString().trim()
if (message.isNotBlank()) {
outLog.info(message)
}
buffer.clear()
}
override fun flush() {
flushBuffer()
super.flush()
}
}, true)
System.setOut(outLogger)
}
@JvmStatic
/**
* 重定向 System.err ERROR 级别
*/
fun redirectErrToError() {
val errLogger = PrintStream(object : OutputStream() {
private val buffer = StringBuilder()
override fun write(b: Int) {
if (b == '\n'.code) {
flushBuffer()
} else {
buffer.append(b.toChar())
}
}
override fun write(b: ByteArray, off: Int, len: Int) {
val str = String(b, off, len)
if (str.contains("\n")) {
val lines = str.split("\n")
lines.forEachIndexed { index, line ->
if (index == lines.size - 1 && !str.endsWith("\n")) {
buffer.append(line)
} else {
buffer.append(line)
flushBuffer()
}
}
} else {
buffer.append(str)
}
}
private fun flushBuffer() {
val message = buffer.toString().trim()
if (message.isNotBlank()) {
errLog.error(message)
}
buffer.clear()
}
override fun flush() {
flushBuffer()
super.flush()
}
}, true)
System.setErr(errLogger)
}
@JvmStatic
/**
* 完全重定向包括第三方库的输出
*/
fun redirectAll() {
redirectOutToInfo()
redirectErrToError()
}
@JvmStatic
/**
* 恢复原始输出流
*/
fun restore() {
System.setOut(originalOut)
System.setErr(originalErr)
} }
} }

View File

@ -0,0 +1,231 @@
/*
* Copyright 2025 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile GsonJsonApi.kt
* LastUpdate 2025-09-15 22:07:43
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json
import com.google.gson.*
import com.mingliqiye.utils.json.converters.JsonConverter
import com.mingliqiye.utils.json.converters.JsonStringConverter
class GsonJsonApi : JsonApi {
private var gsonUnicode: Gson
private var gsonPretty: Gson
private var gsonPrettyUnicode: Gson
private var gson: Gson
constructor() {
gson = GsonBuilder()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
gsonUnicode = GsonBuilder()
.disableHtmlEscaping()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
gsonPretty = GsonBuilder()
.setPrettyPrinting()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
gsonPrettyUnicode = GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
}
constructor(gson: Gson) {
this.gson = gson
.newBuilder()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
this.gsonUnicode = gson
.newBuilder()
.disableHtmlEscaping()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
this.gsonPretty = gson
.newBuilder()
.setPrettyPrinting()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
this.gsonPrettyUnicode = gson
.newBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.create()
}
override fun <T> parse(json: String, clazz: Class<T>): T {
return gson.fromJson(json, clazz)
}
override fun <T> parse(json: String, type: JsonTypeReference<T>): T {
return gson.fromJson(json, type.type)
}
override fun format(obj: Any): String {
return gson.toJson(obj)
}
override fun formatUnicode(obj: Any): String {
return gsonUnicode.toJson(obj)
}
override fun formatPretty(obj: Any): String {
return gsonPretty.toJson(obj)
}
override fun formatPrettyUnicode(obj: Any): String {
return gsonPrettyUnicode.toJson(obj)
}
override fun isValidJson(json: String): Boolean {
return try {
JsonParser.parseString(json)
true
} catch (e: JsonSyntaxException) {
false
} catch (e: Exception) {
false
}
}
override fun merge(vararg jsons: String): String {
val merged = JsonObject()
for (json in jsons) {
if (json.isNullOrEmpty()) {
continue
}
try {
val obj = JsonParser.parseString(json).asJsonObject
for (key in obj.keySet()) {
merged.add(key, obj.get(key))
}
} catch (e: Exception) {
// 忽略无效的 JSON 字符串
}
}
return gson.toJson(merged)
}
override fun getNodeValue(json: String, path: String): String? {
return try {
var element = JsonParser.parseString(json)
val paths = path.split("\\.".toRegex()).toTypedArray()
var current = element
for (p in paths) {
if (current.isJsonObject) {
current = current.asJsonObject.get(p)
} else {
return null
}
if (current == null) {
return null
}
}
if (current.isJsonPrimitive) current.asString else current.toString()
} catch (e: Exception) {
null
}
}
override fun updateNodeValue(json: String, path: String, newValue: Any): String {
return try {
val obj = JsonParser.parseString(json).asJsonObject
val paths = path.split("\\.".toRegex()).toTypedArray()
var current = obj
// 导航到倒数第二层
for (i in 0 until paths.size - 1) {
val p = paths[i]
if (!current.has(p) || !current.get(p).isJsonObject) {
current.add(p, JsonObject())
}
current = current.getAsJsonObject(p)
}
// 设置最后一层的值
val lastPath = paths[paths.size - 1]
val element = gson.toJsonTree(newValue)
current.add(lastPath, element)
gson.toJson(obj)
} catch (e: Exception) {
json
}
}
override fun <T, D> convert(source: T, destinationClass: Class<D>): D {
val json = gson.toJson(source)
return gson.fromJson(json, destinationClass)
}
override fun <T, D> convert(source: T, destinationType: JsonTypeReference<D>): D {
val json = gson.toJson(source)
return gson.fromJson(json, destinationType.type)
}
override fun addJsonConverter(c: JsonConverter<*, *>) {
c.getStringConverter()?.let {
gson = gson
.newBuilder()
.registerTypeAdapter(
it.tClass,
it.gsonJsonStringConverterAdapter
)
.create()
gsonUnicode = gsonUnicode
.newBuilder()
.registerTypeAdapter(
it.tClass,
it.gsonJsonStringConverterAdapter
)
.create()
gsonPretty = gsonPretty
.newBuilder()
.registerTypeAdapter(
it.tClass,
it.gsonJsonStringConverterAdapter
)
.create()
gsonPrettyUnicode = gsonPrettyUnicode
.newBuilder()
.registerTypeAdapter(
it.tClass,
it.gsonJsonStringConverterAdapter
)
.create()
}
}
override fun addJsonStringConverter(c: JsonStringConverter<*>) {
addJsonConverter(c)
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,11 +16,11 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile JacksonJsonApi.kt * CurrentFile JacksonJsonApi.kt
* LastUpdate 2026-02-05 14:41:27 * LastUpdate 2025-09-15 22:07:43
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.json.api package com.mingliqiye.utils.json
import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonProcessingException import com.fasterxml.jackson.core.JsonProcessingException
@ -28,10 +28,9 @@ import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.ObjectReader import com.fasterxml.jackson.databind.ObjectReader
import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.databind.node.ObjectNode
import com.mingliqiye.utils.exception.JsonException import com.mingliqiye.utils.json.converters.JsonConverter
import com.mingliqiye.utils.json.api.base.JsonApi import com.mingliqiye.utils.json.converters.JsonStringConverter
import com.mingliqiye.utils.json.api.type.JsonTypeReference import java.io.IOException
import com.mingliqiye.utils.json.converters.base.BaseJsonConverter
/** /**
* 基于Jackson的JSON处理实现类提供JSON字符串解析格式化合并节点操作等功能 * 基于Jackson的JSON处理实现类提供JSON字符串解析格式化合并节点操作等功能
@ -53,7 +52,7 @@ class JacksonJsonApi : JsonApi {
* @param objectMapper 自定义的ObjectMapper实例 * @param objectMapper 自定义的ObjectMapper实例
*/ */
constructor(objectMapper: ObjectMapper) { constructor(objectMapper: ObjectMapper) {
this.objectMapper = objectMapper this.objectMapper = objectMapper.copy()
} }
/** /**
@ -68,7 +67,7 @@ class JacksonJsonApi : JsonApi {
override fun <T> parse(json: String, clazz: Class<T>): T { override fun <T> parse(json: String, clazz: Class<T>): T {
return try { return try {
objectMapper.readValue(json, clazz) objectMapper.readValue(json, clazz)
} catch (e: Exception) { } catch (e: IOException) {
throw JsonException("Failed to parse JSON string", e) throw JsonException("Failed to parse JSON string", e)
} }
} }
@ -88,7 +87,7 @@ class JacksonJsonApi : JsonApi {
objectMapper.constructType(type.type) objectMapper.constructType(type.type)
) )
reader.readValue(json) reader.readValue(json)
} catch (e: Exception) { } catch (e: IOException) {
throw JsonException("Failed to parse JSON string", e) throw JsonException("Failed to parse JSON string", e)
} }
} }
@ -103,17 +102,21 @@ class JacksonJsonApi : JsonApi {
override fun format(obj: Any): String { override fun format(obj: Any): String {
return try { return try {
objectMapper.writeValueAsString(obj) objectMapper.writeValueAsString(obj)
} catch (e: Exception) { } catch (e: JsonProcessingException) {
throw JsonException( throw JsonException(
"Failed to format object to JSON string", e "Failed to format object to JSON string",
e
) )
} }
} }
override fun formatUnicode(obj: Any): String { override fun formatUnicode(obj: Any): String {
return try { return try {
objectMapper.writer().with(JsonGenerator.Feature.ESCAPE_NON_ASCII).writeValueAsString(obj) objectMapper
} catch (e: Exception) { .writer()
.with(JsonGenerator.Feature.ESCAPE_NON_ASCII)
.writeValueAsString(obj)
} catch (e: JsonProcessingException) {
throw JsonException(e) throw JsonException(e)
} }
} }
@ -127,21 +130,27 @@ class JacksonJsonApi : JsonApi {
*/ */
override fun formatPretty(obj: Any): String { override fun formatPretty(obj: Any): String {
return try { return try {
objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj) objectMapper
} catch (e: Exception) { .writerWithDefaultPrettyPrinter()
.writeValueAsString(obj)
} catch (e: JsonProcessingException) {
throw JsonException( throw JsonException(
"Failed to format object to pretty JSON string", e "Failed to format object to pretty JSON string",
e
) )
} }
} }
override fun formatPrettyUnicode(obj: Any): String { override fun formatPrettyUnicode(obj: Any): String {
return try { return try {
objectMapper.writerWithDefaultPrettyPrinter().with(JsonGenerator.Feature.ESCAPE_NON_ASCII) objectMapper
.writerWithDefaultPrettyPrinter()
.with(JsonGenerator.Feature.ESCAPE_NON_ASCII)
.writeValueAsString(obj) .writeValueAsString(obj)
} catch (e: Exception) { } catch (e: JsonProcessingException) {
throw JsonException( throw JsonException(
"Failed to format object to pretty JSON string", e "Failed to format object to pretty JSON string",
e
) )
} }
} }
@ -177,7 +186,8 @@ class JacksonJsonApi : JsonApi {
if (node.isObject) { if (node.isObject) {
result.setAll<JsonNode>(node as ObjectNode) result.setAll<JsonNode>(node as ObjectNode)
} }
} catch (e: Exception) { } catch (e: IOException) {
// 忽略无效的JSON字符串
} }
} }
return try { return try {
@ -203,7 +213,7 @@ class JacksonJsonApi : JsonApi {
node = node.get(p) node = node.get(p)
} }
node.asText() node.asText()
} catch (e: Exception) { } catch (e: IOException) {
throw JsonException("Failed to get node value", e) throw JsonException("Failed to get node value", e)
} }
} }
@ -237,14 +247,15 @@ class JacksonJsonApi : JsonApi {
if (current is ObjectNode) { if (current is ObjectNode) {
val parent: ObjectNode = current val parent: ObjectNode = current
parent.set<JsonNode>( parent.set<JsonNode>(
paths[paths.size - 1], objectMapper.valueToTree(newValue) paths[paths.size - 1],
objectMapper.valueToTree(newValue)
) )
} }
objectMapper.writeValueAsString(objectNode) objectMapper.writeValueAsString(objectNode)
} }
json json
} catch (e: Exception) { } catch (e: IOException) {
throw JsonException("Failed to update node value", e) throw JsonException("Failed to update node value", e)
} }
} }
@ -258,12 +269,8 @@ class JacksonJsonApi : JsonApi {
* @param <D> 目标对象类型 * @param <D> 目标对象类型
* @return 转换后的对象 * @return 转换后的对象
*/ */
override fun <D> convert(source: Any, destinationClass: Class<D>): D { override fun <T, D> convert(source: T, destinationClass: Class<D>): D {
try {
return objectMapper.convertValue(source, destinationClass) return objectMapper.convertValue(source, destinationClass)
} catch (e: Exception) {
throw JsonException("Failed to update node value", e)
}
} }
/** /**
@ -275,21 +282,20 @@ class JacksonJsonApi : JsonApi {
* @param <D> 目标对象类型 * @param <D> 目标对象类型
* @return 转换后的对象 * @return 转换后的对象
*/ */
override fun <D> convert(source: Any, destinationType: JsonTypeReference<D>): D { override fun <T, D> convert(source: T, destinationType: JsonTypeReference<D>): D {
try {
return objectMapper.convertValue( return objectMapper.convertValue(
source, objectMapper.constructType(destinationType.type) source,
objectMapper.constructType(destinationType.type)
) )
} catch (e: Exception) { }
throw JsonException("Failed to update node value", e)
override fun addJsonConverter(c: JsonConverter<*, *>) {
c.getStringConverter()?.let {
objectMapper.registerModule(it.jacksonJsonStringConverterAdapter.jacksonModule)
} }
} }
override fun addJsonConverter(c: BaseJsonConverter<*, *>) { override fun addJsonStringConverter(c: JsonStringConverter<*>) {
try { addJsonConverter(c)
objectMapper.registerModule(c.getJacksonModule())
} catch (e: Exception) {
throw JsonException("Failed to update node value", e)
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,128 +16,24 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile JsonApi.kt * CurrentFile JsonApi.kt
* LastUpdate 2026-02-04 21:00:48 * LastUpdate 2025-09-15 22:32:50
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.json.api.base package com.mingliqiye.utils.json
import com.mingliqiye.utils.json.api.type.JsonTypeReference import com.mingliqiye.utils.json.converters.JsonConverter
import com.mingliqiye.utils.json.api.type.listType import com.mingliqiye.utils.json.converters.JsonStringConverter
import com.mingliqiye.utils.json.converters.base.BaseJsonConverter
import java.io.* import java.io.*
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
/** /**
* JSON处理接口提供JSON字符串与Java对象之间的相互转换功能 * JSON处理接口提供JSON字符串与Java对象之间的相互转换功能
*/ */
interface JsonApi { interface JsonApi {
companion object {
/**
* 将JSON字符串解析为指定泛型类型对象
*
* @param json 待解析的JSON字符串
* @param T 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
inline fun <reified T> JsonApi.parse(json: String): T = parse(json, object : JsonTypeReference<T>() {})
/**
* 将JSON字节数组解析为指定泛型类型对象
*
* @param json 待解析的JSON字节数组
* @param T 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
inline fun <reified T> JsonApi.parse(json: ByteArray): T = parse(json, object : JsonTypeReference<T>() {})
/**
* 将JSON字符串解析为指定泛型类型对象解析失败时返回默认值
*
* @param json 待解析的JSON字符串
* @param defect 解析失败时返回的默认值
* @param T 泛型参数表示目标对象的类型
* @return 解析后的对象实例或默认值
*/
inline fun <reified T> JsonApi.parse(json: String, defect: T): T =
parse(json, object : JsonTypeReference<T>() {}, defect)
/**
* 从文件路径读取JSON并解析为指定泛型类型对象
*
* @param path 文件路径
* @param T 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
inline fun <reified T> JsonApi.parseFrom(path: String): T = parseFrom(path, object : JsonTypeReference<T>() {})
/**
* 从文件读取JSON并解析为指定泛型类型对象
*
* @param path 文件对象
* @param T 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
inline fun <reified T> JsonApi.parseFrom(path: File): T = parseFrom(path, object : JsonTypeReference<T>() {})
/**
* 从输入流读取JSON并解析为指定泛型类型对象
*
* @param path 输入流
* @param T 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
inline fun <reified T> JsonApi.parseFrom(path: InputStream): T =
parseFrom(path, object : JsonTypeReference<T>() {})
/**
* 从路径读取JSON并解析为指定泛型类型对象
*
* @param path 路径对象
* @param T 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
inline fun <reified T> JsonApi.parseFrom(path: Path): T = parseFrom(path, object : JsonTypeReference<T>() {})
/**
* 将JSON字符串解析为指定键值类型的Map集合
*
* @param json 待解析的JSON字符串
* @param K 泛型参数表示Map中键的类型
* @param V 泛型参数表示Map中值的类型
* @return 解析后的Map集合
*/
inline fun <reified K, reified V> JsonApi.parseMap(
json: String
): MutableMap<K, V> = parseMap(json, K::class.java, V::class.java)
/**
* 使用内联函数和reified类型参数将源对象转换为目标类型的对象
*
* @param T 源对象的类型
* @param D 目标对象的类型通过reified类型参数推断
* @param source 需要转换的源对象
* @return 转换后的目标类型对象
*/
@JvmStatic
inline fun <reified D> JsonApi.convert(source: Any): D = convert(source, object : JsonTypeReference<D>() {})
/**
* 添加JSON转换器到API中
*
* @param T 需要添加的JSON转换器类
*/
@JvmStatic
inline fun <reified T : BaseJsonConverter<*, *>> JsonApi.addJsonConverter() {
addJsonConverter(T::class.java.newInstance())
}
}
/** /**
* 将JSON字符串解析为指定类型的对象 * 将JSON字符串解析为指定类型的对象
* *
@ -168,52 +64,24 @@ interface JsonApi {
fun formatUnicode(obj: Any): String fun formatUnicode(obj: Any): String
/** @Throws(IOException::class)
* 从文件路径读取JSON并解析为指定类型对象
*
* @param path 文件路径
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(path: String, clazz: Class<T>): T { fun <T> parseFrom(path: String, clazz: Class<T>): T {
return parseFrom(Paths.get(path), clazz) return parseFrom(Paths.get(path), clazz)
} }
/** @Throws(IOException::class)
* 从路径读取JSON并解析为指定类型对象
*
* @param path 路径对象
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(path: Path, clazz: Class<T>): T { fun <T> parseFrom(path: Path, clazz: Class<T>): T {
return parseFrom(path.toFile(), clazz) return parseFrom(path.toFile(), clazz)
} }
/** @Throws(IOException::class)
* 从文件读取JSON并解析为指定类型对象
*
* @param file 文件对象
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(file: File, clazz: Class<T>): T { fun <T> parseFrom(file: File, clazz: Class<T>): T {
Files.newInputStream(file.toPath()).use { inputStream -> Files.newInputStream(file.toPath()).use { inputStream ->
return parseFrom(inputStream, clazz) return parseFrom(inputStream, clazz)
} }
} }
/** @Throws(IOException::class)
* 从输入流读取JSON并解析为指定类型对象
*
* @param inputStream 输入流
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(inputStream: InputStream, clazz: Class<T>): T { fun <T> parseFrom(inputStream: InputStream, clazz: Class<T>): T {
val bytes = ByteArray(1024) val bytes = ByteArray(1024)
ByteArrayOutputStream().use { bos -> ByteArrayOutputStream().use { bos ->
@ -225,52 +93,24 @@ interface JsonApi {
} }
} }
/** @Throws(IOException::class)
* 从文件路径读取JSON并解析为指定泛型类型对象
*
* @param path 文件路径
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(path: String, type: JsonTypeReference<T>): T { fun <T> parseFrom(path: String, type: JsonTypeReference<T>): T {
return parseFrom(Paths.get(path), type) return parseFrom(Paths.get(path), type)
} }
/** @Throws(IOException::class)
* 从路径读取JSON并解析为指定泛型类型对象
*
* @param path 路径对象
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(path: Path, type: JsonTypeReference<T>): T { fun <T> parseFrom(path: Path, type: JsonTypeReference<T>): T {
return parseFrom(path.toFile(), type) return parseFrom(path.toFile(), type)
} }
/** @Throws(IOException::class)
* 从文件读取JSON并解析为指定泛型类型对象
*
* @param file 文件对象
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(file: File, type: JsonTypeReference<T>): T { fun <T> parseFrom(file: File, type: JsonTypeReference<T>): T {
Files.newInputStream(file.toPath()).use { inputStream -> Files.newInputStream(file.toPath()).use { inputStream ->
return parseFrom<T>(inputStream, type) return parseFrom<T>(inputStream, type)
} }
} }
/** @Throws(IOException::class)
* 从输入流读取JSON并解析为指定泛型类型对象
*
* @param inputStream 输入流
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
fun <T> parseFrom(inputStream: InputStream, type: JsonTypeReference<T>): T { fun <T> parseFrom(inputStream: InputStream, type: JsonTypeReference<T>): T {
val bytes = ByteArray(1024) val bytes = ByteArray(1024)
ByteArrayOutputStream().use { bos -> ByteArrayOutputStream().use { bos ->
@ -316,10 +156,10 @@ interface JsonApi {
* @return 解析后的对象实例或默认值 * @return 解析后的对象实例或默认值
</T> */ </T> */
fun <T> parse(json: String, clazz: Class<T>, defaultValue: T): T { fun <T> parse(json: String, clazz: Class<T>, defaultValue: T): T {
return try { try {
parse(json, clazz) return parse(json, clazz)
} catch (e: Exception) { } catch (e: Exception) {
defaultValue return defaultValue
} }
} }
@ -333,12 +173,14 @@ interface JsonApi {
* @return 解析后的对象实例或默认值 * @return 解析后的对象实例或默认值
**/ **/
fun <T> parse( fun <T> parse(
json: String, type: JsonTypeReference<T>, defaultValue: T json: String,
type: JsonTypeReference<T>,
defaultValue: T
): T { ): T {
return try { try {
parse<T>(json, type) return parse<T>(json, type)
} catch (e: Exception) { } catch (e: Exception) {
defaultValue return defaultValue
} }
} }
@ -360,38 +202,46 @@ interface JsonApi {
return formatPrettyUnicode(obj)!!.toByteArray() return formatPrettyUnicode(obj)!!.toByteArray()
} }
@Throws(IOException::class)
fun formatPretty(obj: Any, file: String) { fun formatPretty(obj: Any, file: String) {
formatPretty(obj, Paths.get(file)) formatPretty(obj, Paths.get(file))
} }
@Throws(IOException::class)
fun formatPretty(obj: Any, file: Path) { fun formatPretty(obj: Any, file: Path) {
formatPretty(obj, file.toFile()) formatPretty(obj, file.toFile())
} }
@Throws(IOException::class)
fun formatPretty(obj: Any, file: File) { fun formatPretty(obj: Any, file: File) {
FileOutputStream(file).use { fos -> FileOutputStream(file).use { fos ->
formatPretty(obj, fos) formatPretty(obj, fos)
} }
} }
@Throws(IOException::class)
fun formatPretty(obj: Any, stream: OutputStream) { fun formatPretty(obj: Any, stream: OutputStream) {
stream.write(formatPrettyBytes(obj)) stream.write(formatPrettyBytes(obj))
} }
@Throws(IOException::class)
fun formatPrettyUnicode(obj: Any, file: String) { fun formatPrettyUnicode(obj: Any, file: String) {
formatPrettyUnicode(obj, Paths.get(file)) formatPrettyUnicode(obj, Paths.get(file))
} }
@Throws(IOException::class)
fun formatPrettyUnicode(obj: Any, file: Path) { fun formatPrettyUnicode(obj: Any, file: Path) {
formatPrettyUnicode(obj, file.toFile()) formatPrettyUnicode(obj, file.toFile())
} }
@Throws(IOException::class)
fun formatPrettyUnicode(obj: Any, file: File) { fun formatPrettyUnicode(obj: Any, file: File) {
FileOutputStream(file).use { fos -> FileOutputStream(file).use { fos ->
formatPrettyUnicode(obj, fos) formatPrettyUnicode(obj, fos)
} }
} }
@Throws(IOException::class)
fun formatPrettyUnicode(obj: Any, stream: OutputStream) { fun formatPrettyUnicode(obj: Any, stream: OutputStream) {
stream.write(formatPrettyUnicodeBytes(obj)) stream.write(formatPrettyUnicodeBytes(obj))
} }
@ -404,38 +254,46 @@ interface JsonApi {
return formatUnicode(obj)!!.toByteArray() return formatUnicode(obj)!!.toByteArray()
} }
@Throws(IOException::class)
fun format(obj: Any, file: String) { fun format(obj: Any, file: String) {
format(obj, Paths.get(file)) format(obj, Paths.get(file))
} }
@Throws(IOException::class)
fun format(obj: Any, file: Path) { fun format(obj: Any, file: Path) {
format(obj, file.toFile()) format(obj, file.toFile())
} }
@Throws(IOException::class)
fun format(obj: Any, file: File) { fun format(obj: Any, file: File) {
FileOutputStream(file).use { fos -> FileOutputStream(file).use { fos ->
format(obj, fos) format(obj, fos)
} }
} }
@Throws(IOException::class)
fun format(obj: Any, stream: OutputStream) { fun format(obj: Any, stream: OutputStream) {
stream.write(formatPrettyBytes(obj)) stream.write(formatPrettyBytes(obj))
} }
@Throws(IOException::class)
fun formatUnicode(obj: Any, file: String) { fun formatUnicode(obj: Any, file: String) {
formatUnicode(obj, Paths.get(file)) formatUnicode(obj, Paths.get(file))
} }
@Throws(IOException::class)
fun formatUnicode(obj: Any, file: Path) { fun formatUnicode(obj: Any, file: Path) {
formatUnicode(obj, file.toFile()) formatUnicode(obj, file.toFile())
} }
@Throws(IOException::class)
fun formatUnicode(obj: Any, file: File) { fun formatUnicode(obj: Any, file: File) {
FileOutputStream(file).use { fos -> FileOutputStream(file).use { fos ->
formatUnicode(obj, fos) formatUnicode(obj, fos)
} }
} }
@Throws(IOException::class)
fun formatUnicode(obj: Any, stream: OutputStream) { fun formatUnicode(obj: Any, stream: OutputStream) {
stream.write(formatPrettyUnicodeBytes(obj)) stream.write(formatPrettyUnicodeBytes(obj))
} }
@ -463,7 +321,9 @@ interface JsonApi {
* @return 解析后的Map集合 * @return 解析后的Map集合
</V></K> */ </V></K> */
fun <K, V> parseMap( fun <K, V> parseMap(
json: String, keyType: Class<K>, valueType: Class<V> json: String,
keyType: Class<K>,
valueType: Class<V>
): MutableMap<K, V> { ): MutableMap<K, V> {
val mapType: JsonTypeReference<MutableMap<K, V>> = object : JsonTypeReference<MutableMap<K, V>>() {} val mapType: JsonTypeReference<MutableMap<K, V>> = object : JsonTypeReference<MutableMap<K, V>>() {}
return parse<MutableMap<K, V>>(json, mapType) return parse<MutableMap<K, V>>(json, mapType)
@ -524,9 +384,10 @@ interface JsonApi {
*/ */
fun updateNodeValue(json: String, path: String, newValue: Any): String fun updateNodeValue(json: String, path: String, newValue: Any): String
fun <D> convert(source: Any, destinationClass: Class<D>): D fun <T, D> convert(source: T, destinationClass: Class<D>): D
fun <D> convert(source: Any, destinationType: JsonTypeReference<D>): D fun <T, D> convert(source: T, destinationType: JsonTypeReference<D>): D
fun addJsonConverter(c: BaseJsonConverter<*, *>) fun addJsonConverter(c: JsonConverter<*, *>)
fun addJsonStringConverter(c: JsonStringConverter<*>)
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -15,16 +15,18 @@
* *
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile BaseType.kt * CurrentFile JsonException.kt
* LastUpdate 2026-02-04 21:54:04 * LastUpdate 2025-09-15 22:32:50
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.base package com.mingliqiye.utils.json
enum class BaseType(val baseCodec: BaseCodec) { class JsonException : RuntimeException {
BASE16(com.mingliqiye.utils.base.BASE16),
BASE64(com.mingliqiye.utils.base.BASE64), constructor(message: String) : super(message)
BASE91(com.mingliqiye.utils.base.BASE91),
BASE256(com.mingliqiye.utils.base.BASE256), constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable) : this(cause.message ?: "", cause)
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,11 +16,11 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile JsonTypeReference.kt * CurrentFile JsonTypeReference.kt
* LastUpdate 2026-02-05 11:12:36 * LastUpdate 2025-09-15 22:32:50
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.json.api.type package com.mingliqiye.utils.json
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type import java.lang.reflect.Type
@ -68,7 +68,8 @@ abstract class JsonTypeReference<T> : Comparable<JsonTypeReference<T>> {
* @return 类型引用实例 * @return 类型引用实例
*/ */
companion object { companion object {
inline fun <reified T> of(): JsonTypeReference<T> { @JvmStatic
fun <T> of(): JsonTypeReference<T> {
return object : JsonTypeReference<T>() {} return object : JsonTypeReference<T>() {}
} }
@ -115,11 +116,6 @@ abstract class JsonTypeReference<T> : Comparable<JsonTypeReference<T>> {
throw IllegalStateException("无法获取原始类型: $type") throw IllegalStateException("无法获取原始类型: $type")
} }
/**
* 判断两个 JsonTypeReference 实例是否相等
* @param other 另一个对象
* @return 是否相等
*/
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other == null || this.javaClass != other.javaClass) return false if (other == null || this.javaClass != other.javaClass) return false
@ -146,10 +142,6 @@ abstract class JsonTypeReference<T> : Comparable<JsonTypeReference<T>> {
return Objects.equals(type, that.type) return Objects.equals(type, that.type)
} }
/**
* 计算当前实例的哈希码
* @return 哈希码值
*/
override fun hashCode(): Int { override fun hashCode(): Int {
if (type is ParameterizedType) { if (type is ParameterizedType) {
val paramType = type as ParameterizedType val paramType = type as ParameterizedType
@ -162,19 +154,10 @@ abstract class JsonTypeReference<T> : Comparable<JsonTypeReference<T>> {
return Objects.hash(type) return Objects.hash(type)
} }
/**
* 返回当前实例的字符串表示形式
* @return 字符串描述
*/
override fun toString(): String { override fun toString(): String {
return "com.mingliqiye.utils.json.JsonTypeReference<${TypeReference.getRawString(type)}>" return "JsonTypeReference{$type}"
} }
/**
* 比较当前实例与另一个实例的大小关系
* @param other 另一个 JsonTypeReference 实例
* @return 比较结果
*/
override fun compareTo(other: JsonTypeReference<T>): Int { override fun compareTo(other: JsonTypeReference<T>): Int {
return this.type.toString().compareTo(other.type.toString()) return this.type.toString().compareTo(other.type.toString())
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,12 +16,12 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile JsonTypeUtils.kt * CurrentFile JsonTypeUtils.kt
* LastUpdate 2026-02-04 21:00:48 * LastUpdate 2025-09-17 11:12:06
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("JsonTypeUtils") @file:JvmName("JsonTypeUtils")
package com.mingliqiye.utils.json.api.type package com.mingliqiye.utils.json
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type import java.lang.reflect.Type

View File

@ -1,644 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JSONA.kt
* LastUpdate 2026-02-05 10:34:30
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.api
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.kotlinModule
import com.mingliqiye.utils.json.api.base.JsonApi
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import com.mingliqiye.utils.json.api.type.listType
import com.mingliqiye.utils.json.converters.base.BaseJsonConverter
import java.io.File
import java.io.InputStream
import java.io.OutputStream
import java.nio.file.Path
/**
* JSON工具类提供静态方法访问JSON API功能
*/
object JSONA {
@JvmStatic
private var jsonApi: JsonApi? = null
/**
* 获取JSON API实例
*
* @return JSON API实例
* @throws NullPointerException 当JSON API未初始化时抛出异常
*/
@Throws(NullPointerException::class)
@JvmStatic
fun getJsonApi(): JsonApi {
if (jsonApi == null) {
throw NullPointerException("jsonApi is null plase setJsonApi first")
}
return jsonApi!!
}
/**
* 设置JSON API实例
*
* @param jsa JSON API实例
*/
@JvmStatic
fun setJsonApi(jsa: JsonApi) {
jsonApi = jsa
}
/**
* 使用反射创建并设置指定类型的JSON API实例
*
* @param T 继承自JsonApi的具体实现类
*/
inline fun <reified T : JsonApi> setJsonApi() {
setJsonApi(T::class.java.newInstance() as JsonApi)
}
/**
* 将JSON字符串解析为指定类型的对象
*
* @param json 待解析的JSON字符串
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parse(json: String, clazz: Class<T>): T = getJsonApi().parse(json, clazz)
/**
* 将JSON字符串解析为指定泛型类型对象
*
* @param json 待解析的JSON字符串
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
inline fun <reified T> parse(json: String): T {
return getJsonApi().parse(json, (object : JsonTypeReference<T>() {}))
}
/**
* 将字节数组形式的JSON解析为指定泛型类型对象
*
* @param json 待解析的JSON字节数组
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
inline fun <reified T> parse(json: ByteArray): T = getJsonApi().parse(json, object : JsonTypeReference<T>() {})
/**
* 将JSON字符串解析为指定泛型类型对象
*
* @param json 待解析的JSON字符串
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parse(json: String, type: JsonTypeReference<T>): T = getJsonApi().parse(json, type)
/**
* 将对象格式化为JSON字符串
*
* @param obj 待格式化的对象
* @return 格式化后的JSON字符串
*/
@JvmStatic
fun format(obj: Any): String = getJsonApi().format(obj)
/**
* 将对象格式化为带Unicode转义的JSON字符串
*
* @param obj 待格式化的对象
* @return 格式化后的带Unicode转义的JSON字符串
*/
@JvmStatic
fun formatUnicode(obj: Any): String = getJsonApi().formatPrettyUnicode(obj)
/**
* 从文件路径解析JSON为指定类型的对象
*
* @param path 文件路径
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(path: String, clazz: Class<T>): T = getJsonApi().parseFrom(path, clazz)
/**
* 从Path对象解析JSON为指定类型的对象
*
* @param path Path对象
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(path: Path, clazz: Class<T>): T = getJsonApi().parseFrom(path, clazz)
/**
* 从File对象解析JSON为指定类型的对象
*
* @param file File对象
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(file: File, clazz: Class<T>): T = getJsonApi().parseFrom(file, clazz)
/**
* 从InputStream解析JSON为指定类型的对象
*
* @param inputStream InputStream对象
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(inputStream: InputStream, clazz: Class<T>): T = getJsonApi().parseFrom(inputStream, clazz)
/**
* 从文件路径解析JSON为指定泛型类型对象
*
* @param path 文件路径
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(path: String, type: JsonTypeReference<T>): T = getJsonApi().parseFrom(path, type)
/**
* 从Path对象解析JSON为指定泛型类型对象
*
* @param path Path对象
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(path: Path, type: JsonTypeReference<T>): T = getJsonApi().parseFrom(path, type)
/**
* 从File对象解析JSON为指定泛型类型对象
*
* @param file File对象
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(file: File, type: JsonTypeReference<T>): T = getJsonApi().parseFrom(file, type)
/**
* 从InputStream解析JSON为指定泛型类型对象
*
* @param inputStream InputStream对象
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parseFrom(inputStream: InputStream, type: JsonTypeReference<T>): T =
getJsonApi().parseFrom(inputStream, type)
/**
* 将字节数组形式的JSON解析为指定类型的对象
*
* @param json 待解析的JSON字节数组
* @param clazz 目标对象的Class类型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parse(json: ByteArray, clazz: Class<T>): T = getJsonApi().parse(json, clazz)
/**
* 将字节数组形式的JSON解析为指定泛型类型对象
*
* @param json 待解析的JSON字节数组
* @param type 目标对象的Type类型支持泛型
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例
*/
@JvmStatic
fun <T> parse(json: ByteArray, type: JsonTypeReference<T>): T = getJsonApi().parse(json, type)
/**
* 将JSON字符串解析为指定类型的对象解析失败时返回默认值
*
* @param json 待解析的JSON字符串
* @param clazz 目标对象的Class类型
* @param defaultValue 解析失败时返回的默认值
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例或默认值
*/
@JvmStatic
fun <T> parse(json: String, clazz: Class<T>, defaultValue: T): T = getJsonApi().parse(json, clazz, defaultValue)
/**
* 将JSON字符串解析为指定泛型类型对象解析失败时返回默认值
*
* @param json 待解析的JSON字符串
* @param type 目标对象的Type类型支持泛型
* @param defaultValue 解析失败时返回的默认值
* @param <T> 泛型参数表示目标对象的类型
* @return 解析后的对象实例或默认值
*/
@JvmStatic
fun <T> parse(
json: String, type: JsonTypeReference<T>, defaultValue: T
): T = getJsonApi().parse(json, type, defaultValue)
/**
* 将对象格式化为美化格式的JSON字符串带缩进和换行
*
* @param obj 待格式化的对象
* @return 格式化后的美化JSON字符串
*/
@JvmStatic
fun formatPretty(obj: Any): String = getJsonApi().formatPretty(obj)
/**
* 将对象格式化为美化格式的JSON字节数组
*
* @param obj 待格式化的对象
* @return 格式化后的美化JSON字节数组
*/
@JvmStatic
fun formatPrettyBytes(obj: Any): ByteArray = getJsonApi().formatPrettyBytes(obj)
/**
* 将对象格式化为带Unicode转义的美化JSON字符串
*
* @param obj 待格式化的对象
* @return 格式化后的带Unicode转义的美化JSON字符串
*/
@JvmStatic
fun formatPrettyUnicode(obj: Any): String = getJsonApi().formatPrettyUnicode(obj)
/**
* 将对象格式化为带Unicode转义的美化JSON字节数组
*
* @param obj 待格式化的对象
* @return 格式化后的带Unicode转义的美化JSON字节数组
*/
@JvmStatic
fun formatPrettyUnicodeBytes(obj: Any): ByteArray = getJsonApi().formatPrettyUnicodeBytes(obj)
/**
* 将对象格式化为美化格式的JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file 文件路径
*/
@JvmStatic
fun formatPretty(obj: Any, file: String) = getJsonApi().formatPretty(obj, file)
/**
* 将对象格式化为美化格式的JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file Path对象
*/
@JvmStatic
fun formatPretty(obj: Any, file: Path) = getJsonApi().formatPretty(obj, file)
/**
* 将对象格式化为美化格式的JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file File对象
*/
@JvmStatic
fun formatPretty(obj: Any, file: File) = getJsonApi().formatPretty(obj, file)
/**
* 将对象格式化为美化格式的JSON字符串并写入输出流
*
* @param obj 待格式化的对象
* @param stream OutputStream对象
*/
@JvmStatic
fun formatPretty(obj: Any, stream: OutputStream) = getJsonApi().formatPretty(obj, stream)
/**
* 将对象格式化为带Unicode转义的美化JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file 文件路径
*/
@JvmStatic
fun formatPrettyUnicode(obj: Any, file: String) = getJsonApi().formatPrettyUnicode(obj, file)
/**
* 将对象格式化为带Unicode转义的美化JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file Path对象
*/
@JvmStatic
fun formatPrettyUnicode(obj: Any, file: Path) = getJsonApi().formatPrettyUnicode(obj, file)
/**
* 将对象格式化为带Unicode转义的美化JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file File对象
*/
@JvmStatic
fun formatPrettyUnicode(obj: Any, file: File) = getJsonApi().formatPrettyUnicode(obj, file)
/**
* 将对象格式化为带Unicode转义的美化JSON字符串并写入输出流
*
* @param obj 待格式化的对象
* @param stream OutputStream对象
*/
@JvmStatic
fun formatPrettyUnicode(obj: Any, stream: OutputStream) = getJsonApi().formatPrettyUnicode(obj, stream)
/**
* 将对象格式化为JSON字节数组
*
* @param obj 待格式化的对象
* @return 格式化后的JSON字节数组
*/
@JvmStatic
fun formatBytes(obj: Any): ByteArray = getJsonApi().formatBytes(obj)
/**
* 将对象格式化为带Unicode转义的JSON字节数组
*
* @param obj 待格式化的对象
* @return 格式化后的带Unicode转义的JSON字节数组
*/
@JvmStatic
fun formatUnicodeBytes(obj: Any): ByteArray = getJsonApi().formatUnicodeBytes(obj)
/**
* 将对象格式化为JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file 文件路径
*/
@JvmStatic
fun format(obj: Any, file: String) = getJsonApi().format(obj, file)
/**
* 将对象格式化为JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file Path对象
*/
@JvmStatic
fun format(obj: Any, file: Path) = getJsonApi().format(obj, file)
/**
* 将对象格式化为JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file File对象
*/
@JvmStatic
fun format(obj: Any, file: File) = getJsonApi().format(obj, file)
/**
* 将对象格式化为JSON字符串并写入输出流
*
* @param obj 待格式化的对象
* @param stream OutputStream对象
*/
@JvmStatic
fun format(obj: Any, stream: OutputStream) = getJsonApi().format(obj, stream)
/**
* 将对象格式化为带Unicode转义的JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file 文件路径
*/
@JvmStatic
fun formatUnicode(obj: Any, file: String) = getJsonApi().formatUnicode(obj, file)
/**
* 将对象格式化为带Unicode转义的JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file Path对象
*/
@JvmStatic
fun formatUnicode(obj: Any, file: Path) = getJsonApi().formatUnicode(obj, file)
/**
* 将对象格式化为带Unicode转义的JSON字符串并写入文件
*
* @param obj 待格式化的对象
* @param file File对象
*/
@JvmStatic
fun formatUnicode(obj: Any, file: File) = getJsonApi().formatUnicode(obj, file)
/**
* 将对象格式化为带Unicode转义的JSON字符串并写入输出流
*
* @param obj 待格式化的对象
* @param stream OutputStream对象
*/
@JvmStatic
fun formatUnicode(obj: Any, stream: OutputStream) = getJsonApi().formatUnicode(obj, stream)
/**
* 将JSON字符串解析为指定元素类型的List集合
*
* @param json 待解析的JSON字符串
* @param elementType List中元素的类型
* @param <T> 泛型参数表示List中元素的类型
* @return 解析后的List集合
*/
@JvmStatic
fun <T> parseList(json: String, elementType: Class<T>): List<T> = parse(json, listType(elementType))
/**
* 将JSON字符串解析为指定元素类型的List集合
*
* @param json 待解析的JSON字符串
* @param <T> 泛型参数表示List中元素的类型
* @return 解析后的List集合
*/
@JvmStatic
inline fun <reified T> parseList(json: String): List<T> = parse(json, listType(T::class.java))
/**
* 将JSON字符串解析为指定键值类型的Map集合
*
* @param json 待解析的JSON字符串
* @param keyType Map中键的类型
* @param valueType Map中值的类型
* @param <K> 泛型参数表示Map中键的类型
* @param <V> 泛型参数表示Map中值的类型
* @return 解析后的Map集合
*/
@JvmStatic
fun <K, V> parseMap(
json: String, keyType: Class<K>, valueType: Class<V>
): MutableMap<K, V> = getJsonApi().parseMap(json, keyType, valueType)
/**
* 将JSON字符串解析为指定键值类型的Map集合
*
* @param json 待解析的JSON字符串
* @param <K> 泛型参数表示Map中键的类型
* @param <V> 泛型参数表示Map中值的类型
* @return 解析后的Map集合
*/
@JvmStatic
inline fun <reified K, reified V> parseMap(
json: String
): MutableMap<K, V> = getJsonApi().parseMap(json, K::class.java, V::class.java)
/**
* 验证字符串是否为有效的JSON格式
*
* @param json 待验证的字符串
* @return 如果是有效的JSON格式返回true否则返回false
*/
@JvmStatic
fun isValidJson(json: String): Boolean = getJsonApi().isValidJson(json)
/**
* 将对象转换为JSON字节数组
*
* @param object 待转换的对象
* @return 转换后的JSON字节数组
*/
@JvmStatic
fun toBytes(obj: Any): ByteArray = getJsonApi().toBytes(obj)
/**
* 将对象转换为美化格式的JSON字节数组
*
* @param object 待转换的对象
* @return 转换后的美化格式JSON字节数组
*/
@JvmStatic
fun toBytesPretty(obj: Any): ByteArray = getJsonApi().toBytesPretty(obj)
/**
* 合并多个JSON字符串为一个JSON对象
*
* @param jsons 待合并的JSON字符串数组
* @return 合并后的JSON字符串
*/
@JvmStatic
fun merge(vararg jsons: String): String = getJsonApi().merge(*jsons)
/**
* 获取JSON字符串中指定路径节点的值
*
* @param json JSON字符串
* @param path 节点路径"user.name"
* @return 节点值的字符串表示
*/
@JvmStatic
fun getNodeValue(json: String, path: String): String? = getJsonApi().getNodeValue(json, path)
/**
* 更新JSON字符串中指定路径节点的值
*
* @param json 原始JSON字符串
* @param path 节点路径"user.name"
* @param newValue 新的节点值
* @return 更新后的JSON字符串
*/
@JvmStatic
fun updateNodeValue(json: String, path: String, newValue: Any): String =
getJsonApi().updateNodeValue(json, path, newValue)
/**
* 将源对象转换为目标类型的对象
*
* @param T 源对象的类型
* @param D 目标对象的类型
* @param source 需要转换的源对象
* @param destinationClass 目标对象的Class类型
* @return 转换后的目标类型对象
*/
@JvmStatic
fun <D> convert(source: Any, destinationClass: Class<D>): D = getJsonApi().convert(source, destinationClass)
/**
* 使用内联函数和reified类型参数将源对象转换为目标类型的对象
*
* @param T 源对象的类型
* @param D 目标对象的类型通过reified类型参数推断
* @param source 需要转换的源对象
* @return 转换后的目标类型对象
*/
@JvmStatic
inline fun <reified D> convert(source: Any): D = getJsonApi().convert(source, object : JsonTypeReference<D>() {})
/**
* 将源对象转换为目标类型的对象使用JsonTypeReference指定目标类型
*
* @param T 源对象的类型
* @param D 目标对象的类型
* @param source 需要转换的源对象
* @param destinationType 目标对象的JsonTypeReference类型引用
* @return 转换后的目标类型对象
*/
@JvmStatic
fun <D> convert(source: Any, destinationType: JsonTypeReference<D>): D =
getJsonApi().convert(source, destinationType)
/**
* 添加JSON转换器到API中
*
* @param c 需要添加的JSON转换器实例
*/
@JvmStatic
fun addJsonConverter(c: BaseJsonConverter<*, *>) = getJsonApi().addJsonConverter(c)
/**
* 使用反射创建并添加指定类型的JSON转换器到API中
*
* @param T 继承自BaseJsonConverter的具体实现类
*/
inline fun <reified T : BaseJsonConverter<*, *>> addJsonConverter() =
addJsonConverter(T::class.java.newInstance())
inline fun <reified T> String.parseJson() = parse<T>(this)
inline fun <reified T> ByteArray.parseJson() = parse<T>(this)
inline fun <reified T> InputStream.parseJson() = this.use { parse<T>(readBytes()) }
inline fun <reified T> File.parseJson() = this.inputStream().parseJson<T>()
inline fun <reified T> Path.parseJson() = this.toFile().inputStream().parseJson<T>()
fun Any.toJson() = format(this)
fun jacksonKotlinObjectMapper(): ObjectMapper = ObjectMapper().jacksonKotlinObjectMapper()
fun ObjectMapper.jacksonKotlinObjectMapper(): ObjectMapper = this.registerModule(kotlinModule())
}

View File

@ -1,76 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile TypeReference.kt
* LastUpdate 2026-02-04 21:00:48
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.api.type
import com.mingliqiye.utils.string.join
import sun.reflect.generics.reflectiveObjects.WildcardTypeImpl
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
class TypeReference(
val rawClass: Type,
vararg paramType: Type
) : ParameterizedType {
private val typeArguments: Array<out Type> = paramType
override fun getActualTypeArguments(): Array<out Type> = typeArguments
override fun getRawType(): Type = rawClass
override fun getOwnerType(): Type? = null
override fun toString(): String = "${getRawString(rawType)}<${
",".join(typeArguments, TypeReference::getRawString)
}>"
companion object {
fun getRawString(s: Any): String {
if (s is Class<*>) {
return s.name
}
if (s is WildcardTypeImpl) {
return getRawString(s.upperBounds[0])
}
if (s is ParameterizedType) {
return of(s).toString()
}
return s.toString()
}
inline fun <reified T> of(): TypeReference {
return of((object : JsonTypeReference<T>() {}).type)
}
fun of(type: Type): TypeReference {
if (type is Class<*>) {
return TypeReference(type)
}
if (type is ParameterizedType) {
return TypeReference(type.rawType, *type.actualTypeArguments)
}
throw IllegalStateException("无法获取类型: $type")
}
}
}

View File

@ -1,112 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile DateTimeJsonConverter.kt
* LastUpdate 2026-02-07 22:13:41
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters
import com.mingliqiye.utils.annotation.DateTimeJsonFormat
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import com.mingliqiye.utils.json.converters.base.AnnotationGetter
import com.mingliqiye.utils.json.converters.base.AnnotationGetter.Companion.get
import com.mingliqiye.utils.json.converters.base.BaseJsonStringConverter
import com.mingliqiye.utils.objects.isNull
import com.mingliqiye.utils.string.isNullish
import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.Formatter
/**
* DateTimeJsonConverter 是一个用于处理 DateTime 类型与 JSON 字符串之间转换的类
* 它继承自 BaseJsonStringConverter提供了序列化convert和反序列化deConvert的功能
*/
class DateTimeJsonConverter private constructor() : BaseJsonStringConverter<DateTime> {
companion object {
private val dateTimeJsonConverter by lazy {
DateTimeJsonConverter()
}
@JvmStatic
fun getJsonConverter(): DateTimeJsonConverter = dateTimeJsonConverter
}
/**
* DateTime 对象转换为 JSON 字符串
*
* @param obj 需要转换的 DateTime 对象可能为 null
* @param annotationGetter 用于获取注解信息的对象用于决定格式化方式
* @return 转换后的字符串如果输入为 null 则返回 null
* @throws Exception 如果在转换过程中发生异常
*/
@Throws(Exception::class)
override fun convert(obj: DateTime?, annotationGetter: AnnotationGetter): String? {
// 如果输入对象为 null直接返回 null
if (obj.isNull()) return null
// 获取 DateTimeJsonFormat 注解信息
val dateTimeJsonFormat: DateTimeJsonFormat? = annotationGetter.get<DateTimeJsonFormat>()
// 根据注解中的格式化规则进行转换
return if (Formatter.NONE != dateTimeJsonFormat?.value && dateTimeJsonFormat != null) {
obj.format(dateTimeJsonFormat.value, dateTimeJsonFormat.repcZero)
} else if (dateTimeJsonFormat?.formatter?.isEmpty() == false) {
obj.format(dateTimeJsonFormat.formatter, dateTimeJsonFormat.repcZero)
} else {
obj.format()
}
}
/**
* JSON 字符串转换为 DateTime 对象
*
* @param obj 需要转换的字符串可能为 null 或空
* @param annotationGetter 用于获取注解信息的对象用于决定解析方式
* @return 解析后的 DateTime 对象如果输入为 null 或空则返回 null
* @throws Exception 如果在解析过程中发生异常
*/
@Throws(Exception::class)
override fun deConvert(obj: String?, annotationGetter: AnnotationGetter): DateTime? {
// 如果输入字符串为 null 或空,直接返回 null
if (obj.isNullish()) return null
// 获取 DateTimeJsonFormat 注解信息
val dateTimeJsonFormat: DateTimeJsonFormat? = annotationGetter.get<DateTimeJsonFormat>()
// 根据注解中的解析规则进行转换
return if (Formatter.NONE != dateTimeJsonFormat?.value && dateTimeJsonFormat != null) {
DateTime.parse(obj, dateTimeJsonFormat.value, dateTimeJsonFormat.repcZero)
} else if (dateTimeJsonFormat?.formatter?.isEmpty() == false) {
DateTime.parse(obj, dateTimeJsonFormat.formatter, dateTimeJsonFormat.repcZero)
} else {
DateTime.parse(obj)
}
}
/**
* 获取当前转换器支持的目标类型引用
*
* @return 返回 DateTime 类型的 JsonTypeReference
* @throws Exception 如果在获取类型引用时发生异常
*/
@Throws(Exception::class)
override fun getFromType(): JsonTypeReference<DateTime> = JsonTypeReference.of<DateTime>()
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2026 mingliqiye * Copyright 2025 mingliqiye
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -15,20 +15,22 @@
* *
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile UUIDToStringConverter.kt * CurrentFile JsonConverter.kt
* LastUpdate 2026-02-04 21:57:43 * LastUpdate 2025-09-15 11:12:07
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
package com.mingliqiye.utils.springboot.converters package com.mingliqiye.utils.json.converters
import com.mingliqiye.utils.uuid.UUID interface JsonConverter<F, T> {
import org.springframework.core.convert.converter.Converter fun convert(obj: F?): T?
import org.springframework.stereotype.Component fun deConvert(obj: T?): F?
val tClass: Class<F>
@Component fun getStringConverter(): JsonStringConverter<F>? {
class UUIDToStringConverter : Converter<UUID, String> { if (this is JsonStringConverter<*>) {
override fun convert(source: UUID): String { return this as JsonStringConverter<F>
return source.getString() }
return null
} }
} }

View File

@ -0,0 +1,251 @@
/*
* Copyright 2025 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JsonStringConverter.kt
* LastUpdate 2025-09-17 19:09:17
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters
import com.alibaba.fastjson2.JSONReader
import com.alibaba.fastjson2.JSONWriter
import com.alibaba.fastjson2.reader.ObjectReader
import com.alibaba.fastjson2.writer.ObjectWriter
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.*
import com.fasterxml.jackson.databind.module.SimpleModule
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.DateTime.Companion.parse
import com.mingliqiye.utils.uuid.UUID
import com.mingliqiye.utils.uuid.UUID.Companion.of
import java.io.IOException
import java.lang.reflect.Type
/**
* JSON转换器接口提供对象与字符串之间的相互转换功能并支持多种JSON库
*
* @param <T> 需要转换的对象类型
</T> */
abstract class JsonStringConverter<T> : JsonConverter<T, String> {
val fastjsonJsonStringConverterAdapter: FastjsonJsonStringConverterAdapter<JsonStringConverter<T>, T>
/**
* 获取 Fastjson 的适配器
* @return 适配器实例
*/
get() = FastjsonJsonStringConverterAdapter.of(this)
val gsonJsonStringConverterAdapter: GsonJsonStringConverterAdapter<JsonStringConverter<T>, T>
/**
* 获取 Gson 的适配器
* @return 适配器实例
*/
get() = GsonJsonStringConverterAdapter.of(this)
val jacksonJsonStringConverterAdapter: JacksonJsonStringConverterAdapter<JsonStringConverter<T>, T>
/**
* 获取 Jackson 的适配器
* @return 适配器实例
*/
get() = JacksonJsonStringConverterAdapter.of(this)
}
class JacksonJsonStringConverterAdapter<T : JsonStringConverter<TT>, TT
> private constructor(val jsonStringConverter: T) {
val jacksonJsonDeserializer: JsonDeserializer<TT?>
/**
* 获取Jackson反序列化器
*
* @return Jackson的JsonDeserializer实例
*/
get() = object : JsonDeserializer<TT?>() {
@Throws(IOException::class)
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): TT? {
if (p.isNaN) return null
return jsonStringConverter.deConvert(p.valueAsString)
}
}
val jacksonJsonSerializer: JsonSerializer<TT?>
/**
* 获取Jackson序列化器
*
* @return Jackson的JsonSerializer实例
*/
get() = object : JsonSerializer<TT?>() {
@Throws(IOException::class)
override fun serialize(
value: TT?,
gen: JsonGenerator,
serializers: SerializerProvider?
) {
if (value == null) {
gen.writeNull()
return
}
gen.writeString(jsonStringConverter.convert(value))
}
}
val jacksonModule: Module
/**
*
* 获取 Jackson 的格式化模块
*
* @return 格式化模块
*/
get() {
val tClass = jsonStringConverter.tClass
val m = SimpleModule(tClass.getSimpleName())
m.addSerializer<TT?>(tClass, this.jacksonJsonSerializer)
m.addDeserializer<TT?>(tClass, this.jacksonJsonDeserializer)
return m
}
companion object {
/**
*
* @param t JSON转换器实例
* @return JSON转换器的适配器
* @param <T> JSON转换器
* @param <TT> JSON转换器的泛型
**/
fun <T : JsonStringConverter<TT>, TT
> of(t: T): JacksonJsonStringConverterAdapter<T, TT> {
return JacksonJsonStringConverterAdapter(t)
}
}
}
class GsonJsonStringConverterAdapter<T : JsonStringConverter<TT>, TT
>(val jsonStringConverter: T) {
val gsonTypeAdapter: TypeAdapter<TT?>
/**
* 获取Gson类型适配器
*
* @return Gson的TypeAdapter实例
*/
get() = object : TypeAdapter<TT?>() {
@Throws(IOException::class)
override fun write(out: JsonWriter, value: TT?) {
if (value == null) {
out.nullValue()
return
}
out.value(jsonStringConverter.convert(value))
}
@Throws(IOException::class)
override fun read(`in`: JsonReader): TT? {
val value = `in`.nextString()
return jsonStringConverter.deConvert(value)
}
}
companion object {
fun <T : JsonStringConverter<TT>, TT
> of(t: T): GsonJsonStringConverterAdapter<T, TT> {
return GsonJsonStringConverterAdapter(t)
}
}
}
class FastjsonJsonStringConverterAdapter<T : JsonConverter<TT, String>, TT
>(val jsonStringConverter: T) {
@Suppress("UNCHECKED_CAST")
val fastJsonObjectWriter: ObjectWriter<T>
/**
* 获取FastJson对象写入器
*
* @return FastJson的ObjectWriter实例
*/
get() = ObjectWriter { writer: JSONWriter?, obj: Any?, _: Any?, _: Type?, _: Long
->
// 如果对象为null则写入null
if (obj == null) {
writer!!.writeNull()
return@ObjectWriter
}
writer!!.writeString(jsonStringConverter.convert(obj as TT))
}
val fastJsonObjectReader: ObjectReader<TT>
/**
* 获取FastJson对象读取器
*
* @return FastJson的ObjectReader实例
*/
get() = ObjectReader { reader: JSONReader?, _: Type?, _: Any?, _: Long
->
val value = reader!!.readString()
jsonStringConverter.deConvert(value)
}
companion object {
fun <T : JsonConverter<TT, String>, TT
> of(t: T): FastjsonJsonStringConverterAdapter<T, TT> {
return FastjsonJsonStringConverterAdapter(t)
}
}
}
class DateTimeJsonConverter : JsonStringConverter<DateTime>() {
override val tClass = DateTime::class.java
override fun convert(obj: DateTime?): String? {
if (obj == null) {
return null
}
return obj.format()
}
override fun deConvert(obj: String?): DateTime? {
if (obj == null) {
return null
}
return parse(
obj
)
}
}
class UUIDJsonStringConverter : JsonStringConverter<UUID>() {
override val tClass: Class<UUID> = UUID::class.java
override fun convert(obj: UUID?): String? {
if (obj == null) {
return null
}
return obj.getString()
}
override fun deConvert(obj: String?): UUID? {
if (obj == null) {
return null
}
return of(obj)
}
}

View File

@ -1,110 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UUIDJsonConverter.kt
* LastUpdate 2026-02-08 01:37:00
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters
import com.mingliqiye.utils.annotation.UUIDJsonFormat
import com.mingliqiye.utils.base.BaseType
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import com.mingliqiye.utils.json.converters.base.AnnotationGetter
import com.mingliqiye.utils.json.converters.base.AnnotationGetter.Companion.get
import com.mingliqiye.utils.json.converters.base.BaseJsonStringConverter
import com.mingliqiye.utils.objects.isNull
import com.mingliqiye.utils.string.isNullish
import com.mingliqiye.utils.uuid.UUID
import com.mingliqiye.utils.uuid.UUIDFormatType
/**
* UUIDJsonConverter 是一个用于处理 UUID 类型与 JSON 字符串之间转换的类
* 它继承自 BaseJsonStringConverter并实现了 convert deConvert 方法
* 分别用于将 UUID 对象序列化为字符串以及反序列化字符串为 UUID 对象
*/
class UUIDJsonConverter private constructor() : BaseJsonStringConverter<UUID> {
companion object {
private val uuidJsonConverter by lazy {
UUIDJsonConverter()
}
@JvmStatic
fun getJsonConverter(): UUIDJsonConverter = uuidJsonConverter
}
/**
* UUID 对象转换为字符串形式
*
* @param obj 需要转换的 UUID 对象可能为 null
* @param annotationGetter 用于获取注解信息的对象
* @return 转换后的字符串如果输入为 null 则返回 null
*/
override fun convert(
obj: UUID?,
annotationGetter: AnnotationGetter
): String? {
// 如果输入对象为 null直接返回 null
if (obj.isNull()) return null
// 获取 UUIDJsonFormat 注解信息,若未找到则使用默认格式
val dateTimeJsonFormat: UUIDJsonFormat = annotationGetter.get<UUIDJsonFormat>() ?: return obj.getString()
// 根据注解中的 base 和 value 属性选择合适的字符串表示方式
return if (BaseType.BASE16 != dateTimeJsonFormat.base) {
obj.getString(dateTimeJsonFormat.base)
} else if (UUIDFormatType.NO_UPPER_SPACE != dateTimeJsonFormat.value) {
obj.getString(dateTimeJsonFormat.value)
} else {
obj.getString()
}
}
/**
* 将字符串反序列化为 UUID 对象
*
* @param obj 需要反序列化的字符串可能为 null 或空
* @param annotationGetter 用于获取注解信息的对象
* @return 反序列化后的 UUID 对象如果输入无效则返回 null
*/
override fun deConvert(
obj: String?,
annotationGetter: AnnotationGetter
): UUID? {
// 如果输入字符串为 null 或空,直接返回 null
if (obj.isNullish()) return null
// 获取 UUIDJsonFormat 注解信息,若未找到则使用默认解析方式
val dateTimeJsonFormat: UUIDJsonFormat = annotationGetter.get<UUIDJsonFormat>() ?: return UUID.of(obj)
// 根据注解中的 base 属性选择合适的解析方式
return if (BaseType.BASE16 != dateTimeJsonFormat.base) {
UUID.of(obj, dateTimeJsonFormat.base)
} else {
UUID.of(obj)
}
}
/**
* 返回当前转换器支持的目标类型引用
*
* @return 表示 UUID 类型的 JsonTypeReference 对象
*/
override fun getFromType() = JsonTypeReference.of<UUID>()
}

View File

@ -1,81 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile AnnotationGetter.kt
* LastUpdate 2026-02-06 16:57:45
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
/**
* 定义一个用于获取注解的接口
* 提供了一个通用方法来根据注解类型获取对应的注解实例
*/
interface AnnotationGetter {
/**
* 根据指定的注解类型获取该类型的注解实例
*
* @param clazz 注解的Class对象表示要获取的注解类型
* @return 返回对应类型的注解实例如果未找到则返回null
*/
fun <T : Annotation> get(clazz: Class<T>): T?
companion object {
/**
* 使用内联函数和重ified类型参数简化注解获取操作
* 通过传入泛型参数自动推断注解类型避免手动传递Class对象
*
* @param T 注解类型必须继承自Annotation
* @return 返回对应类型的注解实例如果未找到则返回null
*/
inline fun <reified T : Annotation> AnnotationGetter.get(): T? = this.get(T::class.java)
/**
* 提供一个默认实现始终返回null
* 可用于需要空注解获取器的场景
*/
val nullGetter = object : AnnotationGetter {
/**
* 始终返回null不执行任何实际逻辑
*
* @param clazz 注解的Class对象未使用
* @return 始终返回null
*/
override fun <T : Annotation> get(clazz: Class<T>): T? = null
}
/**
* 创建一个AnnotationGetter对象用于根据指定的注解类型获取对应的注解实例
*
* @param annotation 要包装的注解实例作为内部逻辑的来源
* @return 返回一个实现了AnnotationGetter接口的匿名对象
*/
fun oneGetter(annotation: Annotation) = object : AnnotationGetter {
/**
* 根据传入的注解类型clazz尝试返回与annotation匹配的注解实例
*
* @param clazz 目标注解类型的Class对象
* @return 如果annotation的类型与clazz一致则返回annotation转换为T类型的实例否则返回null
*/
override fun <T : Annotation> get(clazz: Class<T>): T? =
if (annotation.javaClass == clazz) annotation as T else null
}
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonBigDecimalConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import java.math.BigDecimal
/**
* 接口 [BaseJsonBigDecimalConverter] 定义了一个用于将 JSON 数据转换为 [BigDecimal] 类型的转换器
*
* 此接口继承自 [BaseJsonConverter]并指定目标类型为 [BigDecimal]
* 实现此接口的类需要提供具体的转换逻辑
*
* @param E 转换器处理的源数据类型
*/
interface BaseJsonBigDecimalConverter<E> : BaseJsonConverter<E, BigDecimal> {
/**
* 获取目标类型的引用信息
*
* 该方法返回一个 [JsonTypeReference] 对象表示目标类型为 [BigDecimal]
* 通过调用 [JsonTypeReference.Companion.of] 方法创建类型引用
*
* @return 目标类型 [BigDecimal] 的类型引用
* @throws Exception 如果在获取类型引用时发生异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<BigDecimal>()
}

View File

@ -1,45 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonBigIntegerConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import java.math.BigInteger
/**
* 接口 [BaseJsonBigIntegerConverter] 定义了一个用于将 JSON 数据转换为 `BigInteger` 类型的转换器
* 该接口继承自 [BaseJsonConverter]并指定了泛型参数 [E] `BigInteger`
*
* @param E 表示需要转换的目标类型由实现类具体指定
*/
interface BaseJsonBigIntegerConverter<E> : BaseJsonConverter<E, BigInteger> {
/**
* 获取目标类型的引用用于 JSON 反序列化时确定目标类型
* 该方法重写了父接口中的 [getToType] 方法并返回 `BigInteger` 类型的引用
*
* @return 返回 [JsonTypeReference] 对象表示 `BigInteger` 类型的引用
* @throws Exception 如果在获取类型引用过程中发生异常则抛出该异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<BigInteger>()
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonBooleanConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* 接口 [BaseJsonBooleanConverter] 定义了一个用于处理布尔类型 JSON 转换的基础转换器
*
* 该接口继承自 [BaseJsonConverter]并专门用于将某种类型 [E] 转换为布尔类型 [Boolean]
* 实现该接口的类需要提供具体的转换逻辑
*/
interface BaseJsonBooleanConverter<E> : BaseJsonConverter<E, Boolean> {
/**
* 获取目标类型的引用信息
*
* 该方法返回一个 [JsonTypeReference] 对象表示目标类型为 [Boolean]
* 此方法重写了父接口中的定义并通过 [JsonTypeReference.Companion.of] 方法获取布尔类型的引用
*
* @return [JsonTypeReference<Boolean>] 表示布尔类型的引用
* @throws Exception 如果在获取类型引用时发生异常则抛出此异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<Boolean>()
}

View File

@ -1,43 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonByteConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* BaseJsonByteConverter 是一个接口继承自 BaseJsonConverter用于定义字节类型Byte JSON 转换器
*
* 该接口的主要作用是提供一个标准的字节类型转换实现并通过 getToType 方法返回目标类型的引用
*
* @param E 泛型参数表示需要转换的目标对象类型
*/
interface BaseJsonByteConverter<E> : BaseJsonConverter<E, Byte> {
/**
* 获取目标类型的引用用于标识转换的目标类型为 Byte
*
* @return 返回 JsonTypeReference 类型的实例表示目标类型为 Byte
* @throws Exception 如果在获取类型引用过程中发生异常则抛出该异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<Byte>()
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonConverter.kt
* LastUpdate 2026-02-08 01:22:35
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
/**
* BaseJsonConverter 是一个泛型接口用于定义 JSON 转换器的基本行为
*
* 该接口继承自 JackSonJsonConverter并通过泛型参数 F T 定义了转换的源类型和目标类型
* 实现该接口的类需要提供具体的 JSON 转换逻辑
*
* @param F 源类型表示需要被转换的数据类型
* @param T 目标类型表示转换后的数据类型
*/
interface BaseJsonConverter<F, T> : JackSonJsonConverter<F, T>

View File

@ -1,42 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonDoubleConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* BaseJsonDoubleConverter 是一个接口继承自 BaseJsonConverter
* 用于定义将 JSON 数据转换为 Double 类型的转换器
*
* @param E 泛型参数表示需要转换的目标类型
*/
interface BaseJsonDoubleConverter<E> : BaseJsonConverter<E, Double> {
/**
* 获取目标类型的引用用于标识转换的目标类型为 Double
*
* @return 返回 JsonTypeReference<Double> 类型的实例表示目标类型为 Double
* @throws Exception 如果在获取类型引用时发生异常则抛出该异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<Double>()
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonFloatConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* 接口 [BaseJsonFloatConverter] 定义了一个用于处理浮点数类型 JSON 转换的基础转换器
*
* 该接口继承自 [BaseJsonConverter]并指定泛型参数 [E] [Float]
* 表示将某种类型 [E] 转换为 [Float] 类型的 JSON 数据
*/
interface BaseJsonFloatConverter<E> : BaseJsonConverter<E, Float> {
/**
* 获取目标类型的引用信息
*
* 该方法重写了父接口中的 [getToType] 方法返回 [Float] 类型的 [JsonTypeReference] 实例
* 用于标识当前转换器的目标类型为 [Float]
*
* @return [JsonTypeReference] 表示 [Float] 类型的引用信息
* @throws Exception 如果在获取类型引用时发生异常则抛出此异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<Float>()
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonIntConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* 接口 [BaseJsonIntConverter] 是一个泛型接口继承自 [BaseJsonConverter]
* 用于定义将 JSON 数据转换为 [Int] 类型的转换器
*
* @param E 表示需要转换的目标类型通常是一个具体的业务实体或数据模型
*/
interface BaseJsonIntConverter<E> : BaseJsonConverter<E, Int> {
/**
* 获取目标类型的引用信息
*
* 该方法重写了父接口中的 [getToType] 方法返回 [Int] 类型的 [JsonTypeReference] 实例
* 用于标识当前转换器的目标类型为 [Int]
*
* @return 返回 [JsonTypeReference] 的实例表示目标类型为 [Int]
* @throws Exception 如果在获取类型引用时发生异常则抛出该异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<Int>()
}

View File

@ -1,43 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonLongConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* 接口 [BaseJsonLongConverter] 定义了一个用于将 JSON 数据转换为 Long 类型的转换器
*
* 此接口继承自 [BaseJsonConverter]并指定泛型参数 [E] [Long]
* 表示该转换器处理的是从类型 [E] [Long] 的转换
*/
interface BaseJsonLongConverter<E> : BaseJsonConverter<E, Long> {
/**
* 获取目标类型的引用用于标识此转换器的目标类型为 [Long]
*
* @return 返回 [JsonTypeReference] 的实例表示目标类型为 [Long]
* @throws Exception 如果在获取类型引用时发生异常则抛出此异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<Long>()
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonShortConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* 接口 [BaseJsonShortConverter] 定义了一个用于将 JSON 数据转换为 Short 类型的转换器
*
* 该接口继承自 [BaseJsonConverter]并指定泛型参数 [E] [Short]
* 表示该转换器处理的源类型为 [E]目标类型为 [Short]
*/
interface BaseJsonShortConverter<E> : BaseJsonConverter<E, Short> {
/**
* 获取目标类型的引用信息
*
* 该方法重写了父接口中的 [getToType] 方法返回 [Short] 类型的 [JsonTypeReference] 实例
* 通过 [JsonTypeReference.Companion.of] 方法创建类型引用
*
* @return [JsonTypeReference] 表示 [Short] 类型的引用
* @throws Exception 如果在获取类型引用过程中发生异常则抛出该异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<Short>()
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonStringConverter.kt
* LastUpdate 2026-02-05 11:20:59
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* 接口 [BaseJsonStringConverter] 定义了一个用于 JSON 字符串转换的基础接口
*
* 该接口继承自 [BaseJsonConverter]并指定泛型参数 [E] [String]
* 表示将类型 [E] 转换为字符串类型的 JSON 数据
*/
interface BaseJsonStringConverter<E> : BaseJsonConverter<E, String> {
/**
* 获取目标类型的引用信息
*
* 该方法重写了父接口中的 [getToType] 方法返回一个表示 [String] 类型的 [JsonTypeReference] 实例
* 此方法可能抛出异常因此使用 [@Throws(Exception::class)] 注解标记
*
* @return 返回一个 [JsonTypeReference] 实例表示目标类型为 [String]
* @throws Exception 如果在获取类型引用时发生错误则抛出此异常
*/
@Throws(Exception::class)
override fun getToType() = JsonTypeReference.of<String>()
}

View File

@ -1,59 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JackJsonDeserializer.kt
* LastUpdate 2026-02-08 02:22:46
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.fasterxml.jackson.databind.BeanProperty
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.deser.ContextualDeserializer
class JackJsonDeserializer<F, T>(
val property: BeanProperty? = null,
val jsonConverter: JsonConverter<F, T>
) : JsonDeserializer<F>(), ContextualDeserializer {
override fun deserialize(
p: JsonParser,
ctxt: DeserializationContext?
): F? {
if (p.currentToken == JsonToken.VALUE_NULL) return null
return jsonConverter.deConvert(p.readValueAs(jsonConverter.getToClass()), object : AnnotationGetter {
override fun <T : Annotation> get(clazz: Class<T>): T? = property?.getAnnotation(clazz)
})
}
/**
* 上下文感知方法设置当前属性信息
*
* @param ctxt 反序列化上下文可选参数
* @param property 当前属性信息
* @return 返回当前反序列化器实例
*/
override fun createContextual(
ctxt: DeserializationContext?,
property: BeanProperty?
): JackJsonDeserializer<F, T> {
return JackJsonDeserializer(property, jsonConverter)
}
}

View File

@ -1,85 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JackJsonSerializer.kt
* LastUpdate 2026-02-08 02:27:52
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.BeanProperty
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.ContextualSerializer
import java.math.BigDecimal
import java.math.BigInteger
class JackJsonSerializer<F, T>(
val property: BeanProperty?,
val jsonConverter: JsonConverter<F, T>
) : JsonSerializer<F>(), ContextualSerializer {
/**
* 序列化方法将源对象转换为目标对象并根据目标对象的类型写入 JSON
*
* @param value 源对象可能为 null
* @param gen JSON 生成器用于写入 JSON 数据
* @param provider 序列化提供者可选参数
*/
override fun serialize(
value: F?,
gen: JsonGenerator,
provider: SerializerProvider?
) {
// 执行转换逻辑
val data: T? = jsonConverter.convert(value, object : AnnotationGetter {
override fun <T : Annotation> get(clazz: Class<T>): T? = property?.getAnnotation(clazz)
})
// 根据目标对象的类型写入对应的 JSON 值
when (data) {
null -> gen.writeNull()
is String -> gen.writeString(data)
is Long -> gen.writeNumber(data)
is Short -> gen.writeNumber(data)
is Byte -> gen.writeNumber(data.toShort())
is Int -> gen.writeNumber(data)
is BigDecimal -> gen.writeNumber(data)
is BigInteger -> gen.writeNumber(data)
is Float -> gen.writeNumber(data)
is Double -> gen.writeNumber(data)
is Boolean -> gen.writeBoolean(data)
else -> throw IllegalArgumentException("not sport data type ${data.javaClass} $data")
}
}
/**
* 上下文感知方法设置当前属性信息
*
* @param prov 序列化提供者可选参数
* @param property 当前属性信息
* @return 返回当前序列化器实例
*/
override fun createContextual(
prov: SerializerProvider?,
property: BeanProperty?
): JsonSerializer<F> {
return JackJsonSerializer(property, jsonConverter)
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JackSonJsonConverter.kt
* LastUpdate 2026-02-08 02:28:49
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.module.SimpleModule
interface JackSonJsonConverter<F, T> : JsonConverter<F, T> {
companion object {
/**
* 扩展ObjectMapper用于注册指定类型的模块
*
* 此函数通过反射创建指定类型的实例并调用其getJacksonModule方法来获取Jackson模块
* 然后将该模块注册到当前ObjectMapper实例中
*
* @param T 必须继承自BaseJsonConverter的泛型类型
* @return 返回注册了模块后的ObjectMapper实例
*/
inline fun <reified T : BaseJsonConverter<*, *>> ObjectMapper.addJsonConverter(): ObjectMapper =
this.registerModule(getJsonConverter<T>().getJacksonModule())
@JvmStatic
fun <T : BaseJsonConverter<*, *>> ObjectMapper.addJsonConverter(clazz: Class<T>): ObjectMapper =
this.registerModule(getJsonConverter(clazz).getJacksonModule())
}
/**
* 创建并返回一个 Jackson 模块该模块包含自定义的序列化器和反序列化器
*
* @return 配置了自定义序列化器和反序列化器的 SimpleModule 对象
*/
fun getJacksonModule(): SimpleModule =
SimpleModule("${getFromClass().name}To${getToClass().name}")
.addSerializer(getFromClass(), JackJsonSerializer(null, this))
.addDeserializer(getFromClass(), JackJsonDeserializer(null, this))
}

Some files were not shown because too many files have changed in this diff Show More