Сохранение Json структуры в KConcreteTypeAdapter
This commit is contained in:
parent
e5728e5ec9
commit
d016aa807c
@ -163,7 +163,7 @@ fun main() {
|
||||
//client.world!!.parallax = Starbound.parallaxAccess["garden"]
|
||||
|
||||
for (i in 0 .. 16) {
|
||||
val item = ItemEntity(client.world!!, Starbound.itemAccess["brain"]!!)
|
||||
val item = ItemEntity(client.world!!, Starbound.itemAccess["money"]!!)
|
||||
|
||||
item.position = Vector2d(600.0 + 16.0 + i, 721.0 + 48.0)
|
||||
item.spawn()
|
||||
|
@ -458,7 +458,5 @@ object Starbound {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items.values.stream().filter { it.currency != null }.forEach(::println)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
package ru.dbotthepony.kstarbound.defs
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.common.collect.ImmutableMap
|
||||
|
||||
/**
|
||||
* Возвращает глубокую неизменяемую копию [input] примитивов/List'ов/Map'ов
|
||||
*/
|
||||
fun enrollList(input: List<Any>, interner: (String) -> String = String::intern): ImmutableList<Any> {
|
||||
val builder = ImmutableList.builder<Any>()
|
||||
|
||||
for (v in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> builder.add(enrollMap(v as Map<String, Any>, interner))
|
||||
is List<*> -> builder.add(enrollList(v as List<Any>, interner))
|
||||
else -> builder.add((v as? String)?.let(interner) ?: v)
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает глубокую неизменяемую копию [input] примитивов/List'ов/Map'ов
|
||||
*/
|
||||
fun enrollMap(input: Map<String, Any>, interner: (String) -> String = String::intern): ImmutableMap<String, Any> {
|
||||
val builder = ImmutableMap.builder<String, Any>()
|
||||
|
||||
for ((k, v) in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> builder.put(interner(k), enrollMap(v as Map<String, Any>))
|
||||
is List<*> -> builder.put(interner(k), enrollList(v as List<Any>))
|
||||
else -> builder.put(interner(k), (v as? String)?.let(interner) ?: v)
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build()
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package ru.dbotthepony.kstarbound.defs
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
|
||||
private fun flattenJsonPrimitive(input: JsonPrimitive): Any {
|
||||
if (input.isNumber) {
|
||||
return input.asNumber
|
||||
} else if (input.isString) {
|
||||
return input.asString.intern()
|
||||
} else {
|
||||
return input.asBoolean
|
||||
}
|
||||
}
|
||||
|
||||
private fun flattenJsonArray(input: JsonArray): ArrayList<Any> {
|
||||
val flattened = ArrayList<Any>(input.size())
|
||||
|
||||
for (v in input) {
|
||||
when (v) {
|
||||
is JsonObject -> flattened.add(flattenJsonObject(v))
|
||||
is JsonArray -> flattened.add(flattenJsonArray(v))
|
||||
is JsonPrimitive -> flattened.add(flattenJsonPrimitive(v))
|
||||
// is JsonNull -> baked.add(null)
|
||||
}
|
||||
}
|
||||
|
||||
return flattened
|
||||
}
|
||||
|
||||
private fun flattenJsonObject(input: JsonObject): Object2ObjectArrayMap<String, Any> {
|
||||
val flattened = Object2ObjectArrayMap<String, Any>()
|
||||
|
||||
for ((k, v) in input.entrySet()) {
|
||||
when (v) {
|
||||
is JsonObject -> flattened[k] = flattenJsonObject(v)
|
||||
is JsonArray -> flattened[k] = flattenJsonArray(v)
|
||||
is JsonPrimitive -> flattened[k] = flattenJsonPrimitive(v)
|
||||
}
|
||||
}
|
||||
|
||||
return flattened
|
||||
}
|
||||
|
||||
fun flattenJsonElement(input: JsonElement): Any? {
|
||||
return when (input) {
|
||||
is JsonObject -> flattenJsonObject(input)
|
||||
is JsonArray -> flattenJsonArray(input)
|
||||
is JsonPrimitive -> flattenJsonPrimitive(input)
|
||||
is JsonNull -> null
|
||||
else -> throw IllegalArgumentException("Unknown argument $input")
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package ru.dbotthepony.kstarbound.defs
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
|
||||
/**
|
||||
* Возвращает глубокую изменяемую копию [input] примитивов/List'ов/Map'ов
|
||||
*/
|
||||
fun flattenList(input: List<Any>): ArrayList<Any> {
|
||||
val list = ArrayList<Any>(input.size)
|
||||
|
||||
for (v in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> list.add(flattenMap(v as Map<String, Any>))
|
||||
is List<*> -> list.add(flattenList(v as List<Any>))
|
||||
else -> list.add(v)
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
fun flattenMap(input: Map<String, Any>): Object2ObjectArrayMap<String, Any> {
|
||||
val map = Object2ObjectArrayMap<String, Any>()
|
||||
|
||||
for ((k, v) in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> map[k] = flattenMap(v as Map<String, Any>)
|
||||
is List<*> -> map[k] = flattenList(v as List<Any>)
|
||||
else -> map[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
@ -1,124 +1,8 @@
|
||||
package ru.dbotthepony.kstarbound.defs
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.google.gson.*
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
|
||||
private fun flattenJsonPrimitive(input: JsonPrimitive): Any {
|
||||
if (input.isNumber) {
|
||||
return input.asNumber
|
||||
} else if (input.isString) {
|
||||
return input.asString.intern()
|
||||
} else {
|
||||
return input.asBoolean
|
||||
}
|
||||
}
|
||||
|
||||
private fun flattenJsonArray(input: JsonArray): ArrayList<Any> {
|
||||
val flattened = ArrayList<Any>(input.size())
|
||||
|
||||
for (v in input) {
|
||||
when (v) {
|
||||
is JsonObject -> flattened.add(flattenJsonObject(v))
|
||||
is JsonArray -> flattened.add(flattenJsonArray(v))
|
||||
is JsonPrimitive -> flattened.add(flattenJsonPrimitive(v))
|
||||
// is JsonNull -> baked.add(null)
|
||||
}
|
||||
}
|
||||
|
||||
return flattened
|
||||
}
|
||||
|
||||
private fun flattenJsonObject(input: JsonObject): Object2ObjectArrayMap<String, Any> {
|
||||
val flattened = Object2ObjectArrayMap<String, Any>()
|
||||
|
||||
for ((k, v) in input.entrySet()) {
|
||||
when (v) {
|
||||
is JsonObject -> flattened[k] = flattenJsonObject(v)
|
||||
is JsonArray -> flattened[k] = flattenJsonArray(v)
|
||||
is JsonPrimitive -> flattened[k] = flattenJsonPrimitive(v)
|
||||
}
|
||||
}
|
||||
|
||||
return flattened
|
||||
}
|
||||
|
||||
fun flattenJsonElement(input: JsonElement): Any? {
|
||||
return when (input) {
|
||||
is JsonObject -> flattenJsonObject(input)
|
||||
is JsonArray -> flattenJsonArray(input)
|
||||
is JsonPrimitive -> flattenJsonPrimitive(input)
|
||||
is JsonNull -> null
|
||||
else -> throw IllegalArgumentException("Unknown argument $input")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает глубокую неизменяемую копию [input] примитивов/List'ов/Map'ов
|
||||
*/
|
||||
fun enrollList(input: List<Any>): ImmutableList<Any> {
|
||||
val builder = ImmutableList.builder<Any>()
|
||||
|
||||
for (v in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> builder.add(enrollMap(v as Map<String, Any>))
|
||||
is List<*> -> builder.add(enrollList(v as List<Any>))
|
||||
else -> builder.add((v as? String)?.intern() ?: v)
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает глубокую неизменяемую копию [input] примитивов/List'ов/Map'ов
|
||||
*/
|
||||
fun enrollMap(input: Map<String, Any>): ImmutableMap<String, Any> {
|
||||
val builder = ImmutableMap.builder<String, Any>()
|
||||
|
||||
for ((k, v) in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> builder.put(k.intern(), enrollMap(v as Map<String, Any>))
|
||||
is List<*> -> builder.put(k.intern(), enrollList(v as List<Any>))
|
||||
else -> builder.put(k.intern(), (v as? String)?.intern() ?: v)
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает глубокую изменяемую копию [input] примитивов/List'ов/Map'ов
|
||||
*/
|
||||
fun flattenList(input: List<Any>): ArrayList<Any> {
|
||||
val list = ArrayList<Any>(input.size)
|
||||
|
||||
for (v in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> list.add(flattenMap(v as Map<String, Any>))
|
||||
is List<*> -> list.add(flattenList(v as List<Any>))
|
||||
else -> list.add(v)
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
fun flattenMap(input: Map<String, Any>): Object2ObjectArrayMap<String, Any> {
|
||||
val map = Object2ObjectArrayMap<String, Any>()
|
||||
|
||||
for ((k, v) in input) {
|
||||
when (v) {
|
||||
is Map<*, *> -> map[k] = flattenMap(v as Map<String, Any>)
|
||||
is List<*> -> map[k] = flattenList(v as List<Any>)
|
||||
else -> map[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
/**
|
||||
* Базовый класс описания прототипа игрового объекта
|
||||
*
|
||||
|
@ -172,6 +172,13 @@ data class ItemDefinition(
|
||||
* Lua скрипты для выполнения
|
||||
*/
|
||||
val scripts: List<String> = listOf(),
|
||||
|
||||
/**
|
||||
* Прототип данного предмета, как JSON структура
|
||||
*
|
||||
* Имеет смысл только для Lua скриптов
|
||||
*/
|
||||
val json: Map<String, Any>,
|
||||
) {
|
||||
data class FossilSetDescription(
|
||||
val price: Long = 0L,
|
||||
@ -221,6 +228,8 @@ data class ItemDefinition(
|
||||
|
||||
.list(ItemDefinition::scripts, transformer = Starbound::readingFolderListTransformer)
|
||||
|
||||
.storesJson()
|
||||
|
||||
.build()
|
||||
|
||||
val FOSSIL_ADAPTER = KConcreteTypeAdapter.Builder(FossilSetDescription::class)
|
||||
|
@ -218,12 +218,14 @@ data class RenderMatch(
|
||||
val PIECE_ADAPTER = KConcreteTypeAdapter.Builder(Piece::class)
|
||||
.plain(Piece::name)
|
||||
.plain(Piece::offset)
|
||||
.build(asList = true)
|
||||
.inputAsList()
|
||||
.build()
|
||||
|
||||
val MATCHER_ADAPTER = KConcreteTypeAdapter.Builder(Matcher::class)
|
||||
.plain(Matcher::offset)
|
||||
.plain(Matcher::ruleName)
|
||||
.build(asList = true)
|
||||
.inputAsList()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,7 +243,8 @@ data class RenderMatchList(
|
||||
val ADAPTER = KConcreteTypeAdapter.Builder(RenderMatchList::class)
|
||||
.plain(RenderMatchList::name)
|
||||
.list(RenderMatchList::list)
|
||||
.build(asList = true)
|
||||
.inputAsList()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,12 @@ import com.google.common.collect.ImmutableList
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.google.common.collect.Interner
|
||||
import com.google.common.collect.Interners
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.google.gson.TypeAdapter
|
||||
import com.google.gson.internal.bind.JsonTreeReader
|
||||
import com.google.gson.internal.bind.TypeAdapters
|
||||
import com.google.gson.stream.JsonReader
|
||||
import com.google.gson.stream.JsonToken
|
||||
@ -14,11 +18,15 @@ import it.unimi.dsi.fastutil.objects.Object2IntArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
import ru.dbotthepony.kstarbound.defs.enrollList
|
||||
import ru.dbotthepony.kstarbound.defs.enrollMap
|
||||
import ru.dbotthepony.kstarbound.defs.flattenJsonElement
|
||||
import ru.dbotthepony.kstarbound.getValue
|
||||
import ru.dbotthepony.kstarbound.setValue
|
||||
import java.lang.reflect.Constructor
|
||||
import kotlin.jvm.internal.DefaultConstructorMarker
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
import kotlin.reflect.full.isSuperclassOf
|
||||
import kotlin.reflect.full.isSupertypeOf
|
||||
import kotlin.reflect.full.memberProperties
|
||||
@ -173,8 +181,9 @@ private data class PackedProperty<Clazz : Any, T>(
|
||||
class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
val bound: KClass<T>,
|
||||
private val types: ImmutableList<PackedProperty<T, *>>,
|
||||
private val asJsonArray: Boolean = false,
|
||||
val stringInterner: Interner<String>
|
||||
val asJsonArray: Boolean,
|
||||
val stringInterner: Interner<String>,
|
||||
val storesJson: Boolean
|
||||
) : TypeAdapter<T>() {
|
||||
private val mapped = Object2IntArrayMap<String>()
|
||||
private val loggedMisses = ObjectArraySet<String>()
|
||||
@ -193,10 +202,17 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
* Обычный конструктор класса (без флагов "значения по умолчанию")
|
||||
*/
|
||||
private val regularFactory: KFunction<T> = bound.constructors.firstOrNull first@{
|
||||
if (it.parameters.size == types.size) {
|
||||
val iterator = types.iterator()
|
||||
var requiredSize = types.size
|
||||
|
||||
for (param in it.parameters) {
|
||||
if (storesJson)
|
||||
requiredSize++
|
||||
|
||||
if (it.parameters.size == requiredSize) {
|
||||
val iterator = types.iterator()
|
||||
val factoryIterator = it.parameters.iterator()
|
||||
|
||||
while (factoryIterator.hasNext() && iterator.hasNext()) {
|
||||
val param = factoryIterator.next()
|
||||
val nextParam = iterator.next()
|
||||
|
||||
val a = param.type
|
||||
@ -207,6 +223,20 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
if (storesJson) {
|
||||
val nextParam = factoryIterator.next()
|
||||
|
||||
if (asJsonArray) {
|
||||
if (!(nextParam.type.classifier as KClass<*>).isSubclassOf(List::class)) {
|
||||
return@first false
|
||||
}
|
||||
} else {
|
||||
if (!(nextParam.type.classifier as KClass<*>).isSubclassOf(Map::class)) {
|
||||
return@first false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return@first true
|
||||
}
|
||||
|
||||
@ -217,14 +247,20 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
* Синтетический конструктор класса, который создаётся Kotlin'ном, для создания классов со значениями по умолчанию
|
||||
*/
|
||||
private val syntheticFactory: Constructor<T>? = try {
|
||||
bound.java.getDeclaredConstructor(*types.map { (it.returnType.classifier as KClass<*>).java }.also {
|
||||
it as MutableList
|
||||
val typelist = types.map { (it.returnType.classifier as KClass<*>).java }.toMutableList()
|
||||
|
||||
for (i in 0 until (if (types.size % 31 == 0) types.size / 31 else types.size / 31 + 1))
|
||||
it.add(Int::class.java)
|
||||
if (storesJson)
|
||||
if (asJsonArray)
|
||||
typelist.add(List::class.java)
|
||||
else
|
||||
typelist.add(Map::class.java)
|
||||
|
||||
it.add(DefaultConstructorMarker::class.java)
|
||||
}.toTypedArray())
|
||||
for (i in 0 until (if (types.size % 31 == 0) types.size / 31 else types.size / 31 + 1))
|
||||
typelist.add(Int::class.java)
|
||||
|
||||
typelist.add(DefaultConstructorMarker::class.java)
|
||||
|
||||
bound.java.getDeclaredConstructor(*typelist.toTypedArray())
|
||||
} catch(_: NoSuchMethodException) {
|
||||
null
|
||||
}
|
||||
@ -270,30 +306,51 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
}
|
||||
|
||||
override fun read(reader: JsonReader): T {
|
||||
if (asJsonArray) {
|
||||
reader.beginArray()
|
||||
} else {
|
||||
reader.beginObject()
|
||||
}
|
||||
|
||||
// таблица присутствия значений (если значение true то на i было значение внутри json)
|
||||
val presentValues = BooleanArray(types.size)
|
||||
val readValues = arrayOfNulls<Any>(types.size)
|
||||
val presentValues = BooleanArray(types.size + (if (storesJson) 1 else 0))
|
||||
val readValues = arrayOfNulls<Any>(types.size + (if (storesJson) 1 else 0))
|
||||
|
||||
if (storesJson)
|
||||
presentValues[presentValues.size - 1] = true
|
||||
|
||||
@Suppress("name_shadowing")
|
||||
var reader = reader
|
||||
|
||||
// Если нам необходимо читать объект как набор данных массива, то давай
|
||||
if (asJsonArray) {
|
||||
val iterator = types.iterator()
|
||||
var fieldId = 0
|
||||
|
||||
if (storesJson) {
|
||||
val readArray = TypeAdapters.JSON_ELEMENT.read(reader)
|
||||
|
||||
if (readArray !is JsonArray) {
|
||||
throw JsonParseException("Expected JSON element to be an Array, ${readArray::class.qualifiedName} given")
|
||||
}
|
||||
|
||||
reader = JsonTreeReader(readArray)
|
||||
readValues[readValues.size - 1] = enrollList(flattenJsonElement(readArray) as List<Any>, stringInterner::intern)
|
||||
}
|
||||
|
||||
reader.beginArray()
|
||||
|
||||
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||
if (!iterator.hasNext()) {
|
||||
val name = fieldId.toString()
|
||||
|
||||
if (loggedMisses.add(name)) {
|
||||
if (currentSymbolicName == null) {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field")
|
||||
if (storesJson) {
|
||||
if (currentSymbolicName == null) {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field, it will be only visible to Lua scripts")
|
||||
} else {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field, it will be only visible to Lua scripts (reading: $currentSymbolicName)")
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field (reading: $currentSymbolicName)")
|
||||
if (currentSymbolicName == null) {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field")
|
||||
} else {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field (reading: $currentSymbolicName)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,16 +374,37 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
}
|
||||
// иначе - читаем как json object
|
||||
} else {
|
||||
if (storesJson) {
|
||||
val readMap = TypeAdapters.JSON_ELEMENT.read(reader)
|
||||
|
||||
if (readMap !is JsonObject) {
|
||||
throw JsonParseException("Expected JSON element to be a Map, ${readMap::class.qualifiedName} given")
|
||||
}
|
||||
|
||||
reader = JsonTreeReader(readMap)
|
||||
readValues[readValues.size - 1] = enrollMap(flattenJsonElement(readMap) as Map<String, Any>, stringInterner::intern)
|
||||
}
|
||||
|
||||
reader.beginObject()
|
||||
|
||||
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||
val name = reader.nextName()
|
||||
val fieldId = mapped.getInt(name)
|
||||
|
||||
if (fieldId == -1) {
|
||||
if (loggedMisses.add(name)) {
|
||||
if (currentSymbolicName == null) {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field")
|
||||
if (storesJson) {
|
||||
if (currentSymbolicName == null) {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field, it will be only visible to Lua scripts")
|
||||
} else {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field, it will be only visible to Lua scripts (reading: $currentSymbolicName)")
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field (reading: $currentSymbolicName)")
|
||||
if (currentSymbolicName == null) {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field")
|
||||
} else {
|
||||
LOGGER.warn("Skipping JSON field with name $name because ${bound.simpleName} has no such field (reading: $currentSymbolicName)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,6 +517,21 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
private val types = ArrayList<PackedProperty<T, *>>()
|
||||
var stringInterner: Interner<String> = Interners.newWeakInterner()
|
||||
|
||||
/**
|
||||
* Принимает ли класс *последним* аргументом JSON объект
|
||||
*
|
||||
* На самом деле, JSON "заворачивается" в [ImmutableMap], или [ImmutableList] если указано [asList]/[inputAsList]
|
||||
*
|
||||
* Поэтому, конструктор класса ОБЯЗАН принимать [Map]/[ImmutableMap] или [List]/[ImmutableList] первым аргументом,
|
||||
* иначе поиск конструктора завершится неудчаей
|
||||
*/
|
||||
var storesJson = false
|
||||
|
||||
fun storesJson(): Builder<T> {
|
||||
storesJson = true
|
||||
return this
|
||||
}
|
||||
|
||||
fun specifyStringInterner(interner: Interner<String>): Builder<T> {
|
||||
stringInterner = interner
|
||||
return this
|
||||
@ -573,12 +666,25 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(asList: Boolean = false): KConcreteTypeAdapter<T> {
|
||||
var asList = false
|
||||
|
||||
fun inputAsMap(): Builder<T> {
|
||||
asList = false
|
||||
return this
|
||||
}
|
||||
|
||||
fun inputAsList(): Builder<T> {
|
||||
asList = true
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): KConcreteTypeAdapter<T> {
|
||||
return KConcreteTypeAdapter(
|
||||
bound = clazz,
|
||||
types = ImmutableList.copyOf(types),
|
||||
asJsonArray = asList,
|
||||
stringInterner = stringInterner
|
||||
stringInterner = stringInterner,
|
||||
storesJson = storesJson
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user