Skip to content

Commit

Permalink
Specify value types for maps in json schema
Browse files Browse the repository at this point in the history
  • Loading branch information
kunyavskiy committed Sep 16, 2023
1 parent 6cafe1f commit 42f84ee
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 56 deletions.
150 changes: 145 additions & 5 deletions schemas/advanced.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,12 @@
]
},
"kotlin.collections.LinkedHashMap?<kotlin.String,Regex>": {
"type": "object"
"type": "object",
"patternProperties": {
".*": {
"type": "string"
}
}
},
"org.icpclive.api.tunning.TeamRegexOverrides?<Regex?,kotlin.collections.LinkedHashMap?,kotlin.collections.LinkedHashMap?>": {
"type": "object",
Expand All @@ -224,17 +229,152 @@
"required": [
]
},
"kotlin.collections.ArrayList?<kotlin.String>": {
"type": "array",
"items": {
"type": "string"
}
},
"kotlin.collections.LinkedHashMap?<kotlin.String,kotlin.String>": {
"type": "object",
"patternProperties": {
".*": {
"type": "string"
}
}
},
"org.icpclive.api.tunning.TeamInfoOverride<kotlin.String?,kotlin.String?,kotlin.collections.ArrayList?,kotlin.String?,kotlin.String?,kotlin.collections.LinkedHashMap?,kotlin.collections.LinkedHashMap?,kotlin.Boolean?,kotlin.Boolean?>": {
"type": "object",
"properties": {
"fullName": {
"type": "string"
},
"displayName": {
"type": "string"
},
"groups": {
"$ref": "#/$defs/kotlin.collections.ArrayList?<kotlin.String>"
},
"organizationId": {
"type": "string"
},
"hashTag": {
"type": "string"
},
"medias": {
"$ref": "#/$defs/kotlin.collections.LinkedHashMap?<org.icpclive.api.TeamMediaType,org.icpclive.api.MediaType?>"
},
"customFields": {
"$ref": "#/$defs/kotlin.collections.LinkedHashMap?<kotlin.String,kotlin.String>"
},
"isHidden": {
"type": "boolean"
},
"isOutOfContest": {
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
]
},
"kotlin.collections.LinkedHashMap?<kotlin.String,org.icpclive.api.tunning.TeamInfoOverride>": {
"type": "object"
"type": "object",
"patternProperties": {
".*": {
"$ref": "#/$defs/org.icpclive.api.tunning.TeamInfoOverride<kotlin.String?,kotlin.String?,kotlin.collections.ArrayList?,kotlin.String?,kotlin.String?,kotlin.collections.LinkedHashMap?,kotlin.collections.LinkedHashMap?,kotlin.Boolean?,kotlin.Boolean?>"
}
}
},
"org.icpclive.api.tunning.GroupInfoOverride<kotlin.Boolean?,kotlin.Boolean?>": {
"type": "object",
"properties": {
"isHidden": {
"type": "boolean"
},
"isOutOfContest": {
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
]
},
"kotlin.collections.LinkedHashMap?<kotlin.String,org.icpclive.api.tunning.GroupInfoOverride>": {
"type": "object"
"type": "object",
"patternProperties": {
".*": {
"$ref": "#/$defs/org.icpclive.api.tunning.GroupInfoOverride<kotlin.Boolean?,kotlin.Boolean?>"
}
}
},
"org.icpclive.api.tunning.OrganizationInfoOverride<kotlin.String?,kotlin.String?>": {
"type": "object",
"properties": {
"displayName": {
"type": "string"
},
"fullName": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
]
},
"kotlin.collections.LinkedHashMap?<kotlin.String,org.icpclive.api.tunning.OrganizationInfoOverride>": {
"type": "object"
"type": "object",
"patternProperties": {
".*": {
"$ref": "#/$defs/org.icpclive.api.tunning.OrganizationInfoOverride<kotlin.String?,kotlin.String?>"
}
}
},
"org.icpclive.api.ScoreMergeMode?<org.icpclive.api.ScoreMergeMode.MAX_PER_GROUP,org.icpclive.api.ScoreMergeMode.MAX_TOTAL,org.icpclive.api.ScoreMergeMode.LAST,org.icpclive.api.ScoreMergeMode.LAST_OK,org.icpclive.api.ScoreMergeMode.SUM>": {
"enum": [
"MAX_PER_GROUP",
"MAX_TOTAL",
"LAST",
"LAST_OK",
"SUM"
]
},
"org.icpclive.api.tunning.ProblemInfoOverride<kotlin.String?,kotlin.String?,Color?,kotlin.Int?,kotlin.Double?,kotlin.Double?,org.icpclive.api.ScoreMergeMode?>": {
"type": "object",
"properties": {
"displayName": {
"type": "string"
},
"fullName": {
"type": "string"
},
"color": {
"type": "string"
},
"ordinal": {
"type": "number"
},
"minScore": {
"type": "number"
},
"maxScore": {
"type": "number"
},
"scoreMergeMode": {
"$ref": "#/$defs/org.icpclive.api.ScoreMergeMode?<org.icpclive.api.ScoreMergeMode.MAX_PER_GROUP,org.icpclive.api.ScoreMergeMode.MAX_TOTAL,org.icpclive.api.ScoreMergeMode.LAST,org.icpclive.api.ScoreMergeMode.LAST_OK,org.icpclive.api.ScoreMergeMode.SUM>"
}
},
"additionalProperties": false,
"required": [
]
},
"kotlin.collections.LinkedHashMap?<kotlin.String,org.icpclive.api.tunning.ProblemInfoOverride>": {
"type": "object"
"type": "object",
"patternProperties": {
".*": {
"$ref": "#/$defs/org.icpclive.api.tunning.ProblemInfoOverride<kotlin.String?,kotlin.String?,Color?,kotlin.Int?,kotlin.Double?,kotlin.Double?,org.icpclive.api.ScoreMergeMode?>"
}
}
},
"org.icpclive.api.MedalTiebreakMode<org.icpclive.api.MedalTiebreakMode.NONE,org.icpclive.api.MedalTiebreakMode.ALL>": {
"enum": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.icpclive.generator.schema


import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands


class MainCommand : CliktCommand() {
override fun run() {}
}

fun main(args: Array<String>) {
MainCommand().subcommands(JsonCommand(), TSCommand()).main(args)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
@file:OptIn(ExperimentalSerializationApi::class)

package org.icpclive.generator.schema


import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.options.*
import dev.adamko.kxstsgen.KxsTsGenerator
import dev.adamko.kxstsgen.core.TsDeclaration
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.required
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.json.*
Expand Down Expand Up @@ -118,7 +113,15 @@ fun SerialDescriptor.toJsonSchemaType(
PrimitiveKind.STRING -> {
JsonObject(
mapOf(
"type" to JsonPrimitive("object")
"type" to JsonPrimitive("object"),
"patternProperties" to JsonObject(
mapOf(
".*" to valuesSerializer.toJsonSchemaType(
processed,
definitions
)
)
)
)
)
}
Expand Down Expand Up @@ -186,46 +189,3 @@ class JsonCommand : CliktCommand(name = "json") {
}
}
}

// This is a copy-pasted generating method to work around a bug.
fun KxsTsGenerator.patchedGenerate(vararg serializers: KSerializer<*>) : String {
return serializers
.toSet()
.flatMap { serializer -> descriptorsExtractor(serializer) }
.toSet()
.flatMap { descriptor -> elementConverter(descriptor) }
.toSet()
.groupBy { element -> sourceCodeGenerator.groupElementsBy(element) }
.mapValues { (_, elements) ->
elements
.filterIsInstance<TsDeclaration>()
.map { element -> sourceCodeGenerator.generateDeclaration(element) }
.filter { it.isNotBlank() }
.toSet() // workaround for https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/issues/110
.joinToString(config.declarationSeparator)
}
.values
.joinToString(config.declarationSeparator)
}

class TSCommand : CliktCommand(name = "type-script") {
private val className by option(help = "Class name for which schema should be generated").multiple()
private val output by option("--output", "-o", help = "File to print output").required()

override fun run() {
val tsGenerator = KxsTsGenerator()
val things = className.map { serializer(Class.forName(it)) }
File(output).printWriter().use {
it.println(tsGenerator.patchedGenerate(*things.toTypedArray()))
}
}
}


class MainCommand : CliktCommand() {
override fun run() {}
}

fun main(args: Array<String>) {
MainCommand().subcommands(JsonCommand(), TSCommand()).main(args)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.icpclive.generator.schema

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.*
import dev.adamko.kxstsgen.KxsTsGenerator
import dev.adamko.kxstsgen.core.TsDeclaration
import kotlinx.serialization.KSerializer
import kotlinx.serialization.serializer
import java.io.File

// This is a copy-pasted generating method to work around a bug.
fun KxsTsGenerator.patchedGenerate(vararg serializers: KSerializer<*>) : String {
return serializers
.toSet()
.flatMap { serializer -> descriptorsExtractor(serializer) }
.toSet()
.flatMap { descriptor -> elementConverter(descriptor) }
.toSet()
.groupBy { element -> sourceCodeGenerator.groupElementsBy(element) }
.mapValues { (_, elements) ->
elements
.filterIsInstance<TsDeclaration>()
.map { element -> sourceCodeGenerator.generateDeclaration(element) }
.filter { it.isNotBlank() }
.toSet() // workaround for https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/issues/110
.joinToString(config.declarationSeparator)
}
.values
.joinToString(config.declarationSeparator)
}

class TSCommand : CliktCommand(name = "type-script") {
private val className by option(help = "Class name for which schema should be generated").multiple()
private val output by option("--output", "-o", help = "File to print output").required()

override fun run() {
val tsGenerator = KxsTsGenerator()
val things = className.map { serializer(Class.forName(it)) }
File(output).printWriter().use {
it.println(tsGenerator.patchedGenerate(*things.toTypedArray()))
}
}
}

0 comments on commit 42f84ee

Please sign in to comment.