diff --git a/build.gradle.kts b/build.gradle.kts index 2d377dd..c15ff60 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("jvm") version "1.9.10" + kotlin("plugin.serialization") version "1.9.10" alias(libs.plugins.shadow) } diff --git a/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt b/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt index 0c3eee5..124a49e 100644 --- a/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt +++ b/src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt @@ -3,7 +3,8 @@ package app.revanced.cli.command import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.options.PatchOption -import kotlinx.serialization.json.* +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import picocli.CommandLine.* import picocli.CommandLine.Help.Visibility.ALWAYS import java.io.File @@ -72,7 +73,7 @@ internal object ListPatchesCommand : Runnable { @Option( names = ["-j", "--json"], - description = ["Output in machine-readable format."], + description = ["Output in machine-readable format. Implies -diopv"], showDefaultValue = ALWAYS ) private var asJson: Boolean = false @@ -136,41 +137,9 @@ internal object ListPatchesCommand : Runnable { } private fun formatJson(patches: List>>): String { - fun Patch.CompatiblePackage.asJson(): JsonObject = buildJsonObject { - put("name", name) - if (withVersions) versions?.let { - put("compatible_versions", JsonArray(it.map(::JsonPrimitive))) - } - } - - fun PatchOption<*>.asJson(): JsonObject = buildJsonObject { - put("title", title) - description?.let { put("description", it) } - put("key", key) - default?.let { put("default", it.toString()) } - values?.let { values -> - put("valid", JsonObject(values.mapValues { entry -> JsonPrimitive(entry.value.toString()) })) - } - } - - fun IndexedValue>.asJson(): JsonObject = let { (index, patch) -> - buildJsonObject { - if (withIndex) put("index", index) - put("name", patch.name) - if (withDescriptions) patch.description?.let { put("description", it) } - if (withOptions && patch.options.isNotEmpty()) { - put("options", JsonArray(patch.options.values.map(PatchOption<*>::asJson))) - } - if (withPackages) { - patch.compatiblePackages?.let { - put("compatible_packages", JsonArray(it.map(Patch.CompatiblePackage::asJson))) - } - } - } - } - - val json = JsonArray(patches.map(IndexedValue>::asJson)) - return json.toString() + val data = patches.map { app.revanced.cli.serialization.Patch(it) } + val format = Json { encodeDefaults = false } + return format.encodeToString(data) } override fun run() { diff --git a/src/main/kotlin/app/revanced/cli/serialization/schema.kt b/src/main/kotlin/app/revanced/cli/serialization/schema.kt new file mode 100644 index 0000000..ba0b023 --- /dev/null +++ b/src/main/kotlin/app/revanced/cli/serialization/schema.kt @@ -0,0 +1,50 @@ +package app.revanced.cli.serialization + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class CompatiblePackage( + val name: String, + @SerialName("compatible_versions") + val compatibleVersions: Set = setOf() +) { + constructor(from: app.revanced.patcher.patch.Patch.CompatiblePackage) : this( + from.name, + from.versions.orEmpty() + ) +} + +@Serializable +data class PatchOption( + val title: String?, + val description: String? = null, + val key: String, + val default: String? = null, + val valid: Map = mapOf(), +) { + constructor(from: app.revanced.patcher.patch.options.PatchOption<*>) : this( + from.title, + from.description, + from.key, + from.default?.toString(), + from.values?.mapValues { it.value.toString() }.orEmpty() + ) +} + +@Serializable +data class Patch( + val index: Int, + val description: String? = null, + val options: List = listOf(), + @SerialName("compatible_packages") + val compatiblePackages: List = listOf(), +) { + constructor(from: IndexedValue>) : this( + from.index, + from.value.description, + from.value.options.values.map(::PatchOption), + from.value.compatiblePackages?.map(::CompatiblePackage).orEmpty(), + ) +} +