Giter Club home page Giter Club logo

kotlinx.serialization's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kotlinx.serialization's Issues

ArrayIndexOutOfBounds in Serialization

hey,

I am getting:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
	at java.util.ArrayList.rangeCheck(ArrayList.java:653)
	at java.util.ArrayList.get(ArrayList.java:429)
	at kotlinx.serialization.internal.SerialClassDescImpl.getElementName(SerialClassDescImpl.kt:44)
	at kotlinx.serialization.json.JSON$JsonOutput.writeElement(JSON.kt:243)
	at kotlinx.serialization.ElementValueOutput.writeStringElementValue(Serialization.kt:312)
	at de.bugreport.SpecialItem.write$Self(structure.kt)
	at de.bugreport.Item$Companion.save(structure.kt)
	at de.bugreport.Item$Companion.save(structure.kt:16)
	at kotlinx.serialization.KOutput.writeSerializableValue(Serialization.kt:133)
	at kotlinx.serialization.KOutput.writeSerializableElementValue(Serialization.kt:174)
	at kotlinx.serialization.internal.MapEntrySerializer.save(CollectionSerializers.kt:191)
	at kotlinx.serialization.internal.MapEntrySerializer.save(CollectionSerializers.kt:183)
	at kotlinx.serialization.KOutput.writeSerializableValue(Serialization.kt:133)
	at kotlinx.serialization.KOutput.writeSerializableElementValue(Serialization.kt:174)
	at kotlinx.serialization.internal.ListLikeSerializer.save(CollectionSerializers.kt:49)
	at kotlinx.serialization.KOutput.writeSerializableValue(Serialization.kt:133)
	at kotlinx.serialization.KOutput.writeSerializableElementValue(Serialization.kt:174)
	at de.bugreport.Registry.write$Self(structure.kt)
	at de.bugreport.Registry$Companion.save(structure.kt)
	at de.bugreport.Registry$Companion.save(structure.kt:7)
	at kotlinx.serialization.KOutput.write(Serialization.kt:93)
	at kotlinx.serialization.json.JSON.stringify(JSON.kt:36)
	at kotlinx.serialization.json.JSON$Companion.stringify(JSON.kt:53)
	at TestSerialization.test(TestSerialization.kt:17)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
	at com.sun.proxy.$Proxy1.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:745)

Here is the class structure:

@Serializable
data class Registry(private val map: Map<String,Item>) {

   @Transient
   val size: Int = map.size
    
    
}

@Serializable
sealed class Item {
    abstract val name: String
}

@Serializable
data class SpecialItem(
        override val name: String
): Item()

and here is how I serialize it:

class TestSerialization {
    
    @Test
    fun test() {
        val registry = Registry(mapOf("Hello" to SpecialItem("Hello")))
        
        println(JSON.Companion.stringify(registry))
    }
    
}

JSON: write type inside json-object rather than in array

Looks like in current implementation objects with polymorphic types are serialized as

[TYPE, { ...OBJECT... }]

It will be more prettily if such objects are serialized as

{
   "@class": TYPE
   ... OBJECT ...
}

Note if the @class is first field in json object then this is may be implemented in single pass parse as for now.

Kotlin Android plugin does not work

Using kotlin-android plugin seems to be not working. Applying the serialization plugin produces the following error.

  • Kotlin 1.2-M1.
  • Gradle 4.2.
org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':redacted'.
	at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:94)
	at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:89)
	at org.gradle.configuration.project.LifecycleProjectEvaluator.doConfigure(LifecycleProjectEvaluator.java:70)
	at org.gradle.configuration.project.LifecycleProjectEvaluator.access$100(LifecycleProjectEvaluator.java:34)
	at org.gradle.configuration.project.LifecycleProjectEvaluator$ConfigureProject.run(LifecycleProjectEvaluator.java:110)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:50)
	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:656)
	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:135)
	at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:35)
	at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62)
	at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:38)
	at org.gradle.initialization.DefaultGradleLauncher$ConfigureBuild.run(DefaultGradleLauncher.java:249)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.initialization.DefaultGradleLauncher.configureBuild(DefaultGradleLauncher.java:167)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:126)
	at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:109)
	at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:78)
	at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:75)
	at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:152)
	at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:100)
	at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:75)
	at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$1.run(RunAsBuildOperationBuildActionRunner.java:43)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:40)
	at org.gradle.tooling.internal.provider.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:51)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:39)
	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:25)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:80)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:53)
	at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:57)
	at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:32)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25)
	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:64)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:29)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:59)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:44)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:45)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:30)
	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
	at org.gradle.util.Swapper.swap(Swapper.java:38)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:295)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.internal.event.ListenerNotificationException: Failed to notify project evaluation listener.
	at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:86)
	at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324)
	at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234)
	at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140)
	at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
	at com.sun.proxy.$Proxy24.afterEvaluate(Unknown Source)
	at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:76)
	... 81 more
Caused by: java.lang.AbstractMethodError
	at org.jetbrains.kotlin.gradle.plugin.SubpluginEnvironment.addSubpluginOptions(KotlinPlugin.kt:683)
	at org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler.processVariant(KotlinPlugin.kt:521)
	at org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler.access$processVariant(KotlinPlugin.kt:372)
	at org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler$handleProject$2$1.invoke(KotlinPlugin.kt:439)
	at org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler$handleProject$2$1.invoke(KotlinPlugin.kt:372)
	at org.jetbrains.kotlin.gradle.plugin.LegacyAndroidAndroidProjectHandler.forEachVariant(LegacyAndroidAndroidProjectHandler.kt:134)
	at org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler$handleProject$2.execute(KotlinPlugin.kt:438)
	at org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler$handleProject$2.execute(KotlinPlugin.kt:372)
	at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:91)
	at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:80)
	at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
	at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230)
	at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149)
	at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
	... 88 more

analyze code for security vulnerabilities

About 2 years ago, a critical remote code execution vulnerability was found in many serialization libraries, including Java serialization an XStream.
In fact the problem is so bad that Java serialization just became useless for any project caring about security.

More details here:

Basically ALL serialization libraries that don't allow the developer to specify a whitelist of classes that are allowed to be deserialized (and instead blindly deserialize whatever they find) are vulnerable.

Please check that the code in kotlinx.serialization is not vulnerable to such attacks, and if it can be in certain conditions, consider either disallowing this or making it really hard from an API point of view.

Can't locate companion serializer for class class List

The documentation mentiones that serializing lists is supported, but I can't seem to get it working.

When running this code in Kotlin-JS:

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JSON

fun main(args: Array<String>) {
    val list = listOf(Foo("a"), Foo("b"))
    println(JSON.stringify(list))
}

@Serializable
data class Foo(val foo: String?)

I get the exception SerializationException "Can't locate companion serializer for class class List". I'm using Kotlin version 1.1.50 and kotlinx.serialization version 0.2.

Fields name policy converters

A very common case of serialization is when API/JSON naming policy conflicts with your code naming, for example, snake case quite popular naming style for JSON fields, but for Kotlin it's camel case. Also, format naming style can be incompatible with JVM (for example field names with dashes).
Gson provides feature to solve that: https://google.github.io/gson/apidocs/com/google/gson/FieldNamingPolicy.html (implementation of FieldNamingStrategy)

In general, it's questionable feature, Moshi doesn't provide it and suggests to use the same case for your model classes.

But it can be a big blocker if you want to migrate to kotlinx.serialization, because you have 3 choices:

  1. Use @SerialName for each field. Tedious and error-prone and requires a lot of refactoring
  2. Rename all your data models to match API name convention. Tedious, requires even more refactoring, violates Kotlin code style guides and backward incompatible.
  3. Write own implementation of JSON (or any other format) that provides such feature, looks like a reasonable solution, but now you have one more copy JSON implementation in your project (because JSON implementation now a part of kotlinx.serialization) with different name, but the same API

Possible solutions:

  1. Add naming policy feature to JSON implementation. Some drawbacks: doesn't work for other formats, debatable nature of this feature, required not for all use cases.
  2. Provide universal API that allows defining name converters. A user can provide own implementation, so not necessary to include it to core fo kotlinx.serialization, works for all formats without additional effort. By default just uses field names as is, so current behavior.
    Possible problems: If you use more than one serialization format, different formats probably require different strategies, so we still should integrate naming policy to format implementation. Also, you sometimes want to use different naming policy for particular requests (from different API), so looks like Serialization format still should provide API to register and use naming policies.

Wrong serialization of parent class

When serializing a class with a serializable parent, the values in the resulting JSON are sorted by order of declaration, the keys are however sorted alphabetically, resulting in a matching that does not make sense.

To give an example - when I have two classes:

@Serializable
open class GameObject(var x: Double = 0.0, var y: Double = 0.0) {
    open val color = "White"
}

@Serializable
class Player: GameObject(0.0, 0.0) {
}

now serializing Player to JSON via JSON.stringify yields

{"color":0.0,"x":0.0,"y":"White"}

which does not make any sense. Seems like a simple bug, should be hopefully easy to fix.

Proguard config

Hi,
can you provide a proguard configuration for kotlinx.serialization? When running proguard over an Android application, the app will crash with
kotlinx.serialization.SerializationException: Can't locate companion serializer for class class
Thanks,
Matthias

Fail parsing JSON with '~' char

I've got an

java.lang.ArrayIndexOutOfBoundsException: 127
	at kotlinx.serialization.json.JSON$Companion.c2tc(JSON.kt:107)
	at kotlinx.serialization.json.JSON$Parser.nextString(JSON.kt:502)
	at kotlinx.serialization.json.JSON$Parser.nextToken(JSON.kt:465)
	at kotlinx.serialization.json.JSON$JsonInput.readElement(JSON.kt:402)
	at Data$Companion.load(main.kt)
	at Data$Companion.load(main.kt:6)
	at kotlinx.serialization.KInput.read(Serialization.kt:187)
	at kotlinx.serialization.json.JSON.parse(JSON.kt:45)
	at kotlinx.serialization.json.JSON$Companion.parse(JSON.kt:55)
	at MainKt.main(main.kt:14)

With this code:

import kotlinx.serialization.*
import kotlinx.serialization.json.JSON

@Serializable
data class Data(val a: Int, @Optional val b: String = "42")

fun main(args: Array<String>) {
    println(JSON.stringify(Data(42))) // {"a": 42, "b": "42"}
    val obj = JSON.parse<Data>("""{"a":42, "b":"~"}""") // Data(a=42, b="~")
}

Property with explicit backing field gets serialized twice

If I try to serialize and deserialize the following structure:

@Serializable
open class GameObject(var x: Double = 0.0, var y: Double = 0.0) {
    var _corners:ArrayList<Int>? = null
    val corners: ArrayList<Int>
        get() {
            if (_corners == null) {
                _corners = arrayListOf(0, 1, 2, 3)
            }

            return _corners!!
        }
}

(e.g. by these methods)

val gameObject = GameObject()
val json = JSON.stringify(gameObject)
val objectCopy = JSON.parse<GameObject>(json)

It errors with a java.lang.NoSuchFieldError, because both "_corners" and "corners" are in the resulting JSON. I know this can be easily fixed by marking the "corners" property as transient, but shouldn't a property that only has a getter not be serialized implicitly?

Support generic user-defined classes

It should be possible to define:

@Serializable class Box<T>(val value: T)

and the enjoy type-safe serialization of Box(42) and Box("foo") alike. This is a meta-issue to discuss design problems surrounding type-safe access to instances of serializers for generic classes.

Provide public API to create typed collection serializers

There is a need to have top-level serializer extension properties named list, set, and map that construct build-in collection serializers from the element serializers with the following signatures:

val <T> KSerializer<T>.list: KSerializer<List<T>>
val <T> KSerializer<T>.set: KSerializer<Set<T>>
val <K, V> Pair<KSerializer<K>, KSerializer<V>>.map: KSerializer<Map<K, V>>

So, a list of serializable Data items received via REST API in str: String could be deserialized conveniently with:

val list = JSON.parse(str, Data.list) // inferred type of list is List<Data>

How to handle nullable fields

This is a question.

I want to parse the output of an API that is not under my control. This API emits JSON that can contain the word null as the value of a field that might otherwise contain a string. Example:

{"description": null}

or

{"description": "Best dog in 6 counties"}

How would one go about defining this field in the data class they wish to serialize/deserialize?

Polymorphic primitive collection serialization.

When serializing a polymorphic collation of primitives using the PolymorphicSerializer the type is always included. Including the type of the primitives might not be necessary. I feel like this is a common use case thus it should be addressed.

Example

val list = listOf(1, 2.0, "a")
val json = JSON.stringify(PolymorphicSerializer.list, list)
println(json) 
// [["kotlin.Int",1],["kotlin.Double",2.0],["kotlin.String","a"]]
// jackson would output the following: [1, 2.0, "a"]

Possible solutions

  1. PolymorphicSerializer::save could omit the type information when serializing primitives or standard collections.
  2. Configurable PolymorphicSerializer class or a different object that behaves as described above. It might be desired to fine tune such behavior.

SerialName for Enums

It's quite common case when deserialization of JSON you want to parse some property to Enum constant, but now Enum constant should have the same name and same case as a property value.
Would be nice to allow annotate enums with SerialName to provide custom naming for a serilized format.
An alternative solution is to use Serializer but looks like overkill for enum classes and SerialName could replace it.

Guava and kotlinx.immutables collections prefab serializers

Not sure what the best way to arrange artifacts for this, but it would be very handy to have prefab seralizers for Guava collections and kotlinx.immutables. For kotlinx.immutables, one could maybe do that in the immutables project itself, but for Guava, it would be very nice to have kotlinx recognize those and pull in appropriate serializers.

Import problems with JSON

Is there a way to configure IntellijIDEA to stop importing the standard JSON from kotlin-javascript? This trips me up multiple times per hour :(.

Deserialization of generic classes is not supported

Even though full type info is available both at compile and run time deserializing types with generic parameters fails due to information lost at type->klass conversion. Test:

@Serializable
data class Box<T>(val value: T)

fun testGenericClassSerialization() {
    val subj = Box("Hello")
    assertEquals(subj, JSON.parse<Box<String>>(JSON.stringify(subj)))
}

@Optional annotation seems excessive

For @Optional annotation default constructor parameter value is required. I guess we could consider all of parameter with default values as optional

Can you add a serializer for Dates?

Hi,
at runtime I get IllegalArgumentException: Can't found internal serializer for class class java.util.Date when I serialize an object that contains a Date.

I tried to write my own KSerializer but I didn't succeed 😢

Readme gradle example not working

In the build.gradle:
Cannot resolve symbol 'serialization_version'
but if you switch to serializationVersion it resolves.


With the basic example, the annotation is red, for both of the above formats.

@Serializable 
// this class does not have a constructor
// Cannot access 'Serializable': it is internal in 'kotlin.io'

Error with implementation by delegation

Given the following domain layer objects:

@Serializable
enum class AvailabilityQuotation {
    GUARANTEEDAVAILABLE,
    ONREQUEST,
    UNKNOWN,
    UNAVAILABLE
}

@Serializable
data class Fee(val id: String, val amount: MonetaryAmount)
@Serializable
data class OptionalExtra(val id: String, val quantity: Int = 0, val price: MonetaryAmount)

@Serializable
interface Offer {
    val id: String
    val image: String
    val basePrice: MonetaryAmount
    val totalPrice: MonetaryAmount
    val availabilityQuotation: AvailabilityQuotation
    val fees: List<Fee>
    val optionalOffers: Map<String, OptionalExtra>
}

@Serializable
data class BaseOffer(
        override val id: String,
        override val image: String,
        override val basePrice: MonetaryAmount,
        override val totalPrice: MonetaryAmount,
        override val availabilityQuotation: AvailabilityQuotation,
        override val fees: List<Fee>,
        override val optionalOffers: Map<String, OptionalExtra>) : Offer

The compiler is failing to run when the I and @serializable annotation to BaseOffer object.

The error is:

C:\work\cartrawler\git\xapp-2\domain (moving-to-kotlin-serialization)
λ gradle -Dtest.single=DomainSerializationTest test --debug-jvm
e: java.lang.IllegalArgumentException: Non-serializable parent of serializable class must have no arg constructor
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl.generateSuperSerializableCall(SerializableCodegenImpl.kt:171)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl.doGenerateConstructorImpl(SerializableCodegenImpl.kt:108)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl.access$doGenerateConstructorImpl(SerializableCodegenImpl.kt:40)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl$generateInternalConstructor$1.invoke(SerializableCodegenImpl.kt:64)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl$generateInternalConstructor$1.invoke(SerializableCodegenImpl.kt:40)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.JVMCodegenUtilKt$generateMethod$1.doGenerateBody(JVMCodegenUtil.kt:109)
        at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$CodegenBased.generateBody(FunctionGenerationStrategy.java:72)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:569)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:332)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:298)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:176)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.JVMCodegenUtilKt.generateMethod(JVMCodegenUtil.kt:106)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl.generateInternalConstructor(SerializableCodegenImpl.kt:64)
        at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen.generateSyntheticInternalConstructor(SerializableCodegen.kt:39)
        at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen.generate(SerializableCodegen.kt:33)
        at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl$Companion.generateSerializableExtensions(SerializableCodegenImpl.kt:51)
        at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationCodegenExtension.generateClassSyntheticParts(SerializationCodegenExtension.kt:28)
        at org.jetbrains.kotlin.codegen.ImplementationBodyCodegen.generateSyntheticPartsAfterBody(ImplementationBodyCodegen.java:384)
        at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:148)
        at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:319)
        at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:303)
        at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassOrObject(PackageCodegenImpl.java:162)
        at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassesAndObjectsInFile(PackageCodegenImpl.java:86)
        at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateFile(PackageCodegenImpl.java:124)
        at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:66)
        at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.generatePackage(KotlinCodegenFacade.java:99)
        at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:77)
        at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:44)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:442)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:153)
        at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:154)
        at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:58)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:103)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:51)
        at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:92)
        at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:303)
        at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:85)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:213)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.access$compileIncrementally(IncrementalCompilerRunner.kt:37)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner$compile$2.invoke(IncrementalCompilerRunner.kt:74)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:87)
        at org.jetbrains.kotlin.daemon.CompileServiceImpl.execIncrementalCompiler(CompileServiceImpl.kt:512)
        at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$execIncrementalCompiler(CompileServiceImpl.kt:96)

Frontend diagnostics (readable errors)

Now all errors are just thrown as exceptions in backend, leading to creepy Compiler Internal Errors for users. These cases requires frontend diagnostics and proper reporting in IDE:

  • Optional/Transient field without default values (#17)
  • Trying to serialize/deserialize field which type is not serializable (#18, #22)
  • Class is not serializable itself
  • Unsupported hierarchy of classes
  • Unsupported visibility of fields (for external serializers)
  • etc...

Polymorphic KSerializer lacks serial ids for protobuf backend

When trying to implement custom serializer, like in #23, protobuf backend fails on serialization because registered polymorphic serializer doesn't provide id tags:

java.util.NoSuchElementException: List is empty.
	at kotlin.collections.CollectionsKt___CollectionsKt.single(_Collections.kt:472)
	at kotlinx.serialization.protobuf.ProtoBuf.getProtoDesc(ProtoBuf.kt:41)
	at kotlinx.serialization.protobuf.ProtoBuf.access$getProtoDesc(ProtoBuf.kt:38)
	at kotlinx.serialization.protobuf.ProtoBuf$ProtobufWriter.getTag(ProtoBuf.kt:67)
	at kotlinx.serialization.protobuf.ProtoBuf$ProtobufWriter.getTag(ProtoBuf.kt:47)
	at kotlinx.serialization.TaggedOutput.writeStringElementValue(Tagged.kt:155)
	at kotlinx.serialization.internal.PolymorphicSerializer.save(Polymorphic.kt:42)
	at kotlinx.serialization.KOutput.writeSerializableValue(Serialization.kt:133)
	at kotlinx.serialization.KOutput.writeSerializableElementValue(Serialization.kt:174)

Lookup of custom serializers

Given following objects:

data class MyKotlinClass(val i: Int, val s: String)

@Serializer(forClass = MyKotlinClass::class)
object MySerializer {}

@Serializable
data class MyWrapper(val a: MyKotlinClass)

Expected: Expression CBOR.dumps(MyWrapper(MyKotlinClass(42, "43"))) should produce correct CBOR byte string.

Actual: Exception in thread "main": kotlinx.serialization.SerializationException: value is not supported, because serialization code for MyWrapper didn't pass correct serializer for field "a"

Dependency on kotlin-reflect

Hi,

thanks for that nice library! I am wondering when you plan to remove the dependency of kotlinx-serialization-runtime on kotlin-reflect. "In thefuture" seems a little vague :-).

The dependency on kotlin-reflect seems to cause problems with dex on Android, breaking the 64k limit even though using multidex.

Thanks,
Matthias

Support deserialisation from JS objects

In Kotlin-JS it would be useful to have the ability to deserialize JS objects to Kotlin objects. The two closest things we can get right now are

  1. Serialize the JS object to Json and deserialize that using this library, this is not very efficient.
  2. Define an external Kotlin variable whose data is provided by JS, this doesn't work for instance methods that are only defined in Kotlin.

Our use case is that we have a bunch of JS code that generates/provides some data, it would require quite a bit of effort to convert it to Kotlin.

Serialization of closures and continuations.

When using continuations it may be very valuable to be able to serialize the continuation. A similar issue applies to lamba's/closures.

Both these "types" are however implicitly created. This allows the compiler to control/generate serialization, but this needs to be implemented (probably by still putting a type annotation on the use site for closures). For continuations it would probably be sufficient to make them serializable iff all members are serializable (including primitives).

This clearly requires changes in code generation by the compiler, but would be very worthwhile and provides a robust broadly applicable replacement for Java Serialization (that can also work in other targets - as long as there is a way for the runtime to determine the concrete type to deserialize).

@SerialName with name using dashes produces invalid JS code

Hi,

I am playing around with multi platform project and I have defined following data class:

@Serializable
data class LoginRequest(
        @SerialName("user-name") var userName: String,
)

when I run JS build then it fails during webpack bundling due to invalid JS code (variable name contains dash which is invalid in JS):

Module parse failed: Unexpected token (549:12)
You may need an appropriate loader to handle this file type.
|     var index, readAll = false;
|     var bitMask0 = 0;
|     var user-name;
|     var input = input_0.readBegin_276rha$(this.serialClassDesc, []);
|     loopLabel: while (true) {
:playground-js:webpack-bundle FAILED

Can you check whether it is bug or whether is it possible to get around this.

Thanks,
Fero

YAML?

Any plans for that?

Also I'm still trying to figure out why I would use this instead of Jackson. I guess x-platform is a big plus, but I'm currently using Kotlin exclusively on the server (i.e. JVM).

Optional field with SerialName

If optional field in data class has the same name as SerialName, parser works properly.

@Optional @SerialName("retweeted_status") val retweeted_status: RetweetedStatus? = null

But if I reasonably want to change it to the other one it fails with the following stack trace.

@Optional @SerialName("retweeted_status") val retweetedStatus: RetweetedStatus? = null

Exception in thread "main" java.lang.NoSuchFieldError: retweeted_status
	at Date.<init>(Main.kt:28)
	at Date$Companion.load(Main.kt)
	at Date$Companion.load(Main.kt:25)
	at kotlinx.serialization.KInput.readSerializableValue(Serialization.kt:212)
	at kotlinx.serialization.ElementValueInput.readSerializableElementValue(Serialization.kt:368)
	at kotlinx.serialization.internal.ListLikeSerializer.readItem(CollectionSerializers.kt:90)
	at kotlinx.serialization.internal.ListLikeSerializer.load(CollectionSerializers.kt:72)
	at kotlinx.serialization.KInput.readSerializableValue(Serialization.kt:212)
	at kotlinx.serialization.ElementValueInput.readSerializableElementValue(Serialization.kt:368)
	at Statuses$Companion.load(Main.kt)
	at Statuses$Companion.load(Main.kt:31)
	at kotlinx.serialization.KInput.read(Serialization.kt:187)
	at kotlinx.serialization.json.JSON.parse(JSON.kt:45)
	at MainKt.getNum(Main.kt:92)
	at MainKt.getNum$default(Main.kt:54)
	at MainKt.main(Main.kt:84)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Problems are reported as Compiler Internal Errors at compile time

e: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Optional field failure in primary constructor of serializable class Packet must have default value
File being compiled and position: (13,71) in /Users/max/Projects/circlet/client-api/src/main/kotlin/circlet/client/api/transport/Packet.kt
PsiElement: @optional val failure: FailureInfo?

JPS Compiler plugin

JPS Compiler plugin is badly needed so that we don't have to delegate build to Gradle.

Javascript collections error

@serializable
data class Config(val rangeSelector: Map<String, String>, val title: Map<String, String>)

val config = JSON.stringify(Config(mapOf("selected" to "1"), mapOf("text" to "AAPL Stock Price")))

gives:
{message_8yp7un$_0: "Can't locate companion serializer for class class Config", cause_th0jdv$_0: null, name: "SerializationException", stack: "SerializationException: Can't locate companion ser…http://localhost:8775/static/bundle.js:20:244144)"}

example from Readme works:
@serializable
data class Data(val a: Int, @optional val b: String = "42")

var data = JSON.stringify(Data(42)

Can't define custom serializer on JVM

When trying to implement custom external serializer, following code:

@Serializer(forClass = Lib::class)
object LibSerializer : KSerializer<Lib> {
    override fun save(output: KOutput, obj: LibNoGetters) {
        output.writeBegin(serialClassDesc)
        output.writeIntElementValue(serialClassDesc, 0, obj.a);
        output.writeStringElementValue(serialClassDesc, 1, obj.b);
        output.writeEnd(serialClassDesc)
    }

    override fun load(input: KInput): LibNoGetters {
        TODO("not implemented")
    }

    override val serialClassDesc: SerialClassDescImpl = SerialClassDescImpl("Lib")

    init {
        serialClassDesc.addElement("a")
        serialClassDesc.addElement("b")
    }
}

produces

Overload resolution ambiguity: 
public open val serialClassDesc: SerialClassDescImpl defined in LibSerializer
public open val serialClassDesc: KSerialClassDesc defined in LibSerializer

Serialize a ByteArray in a ProtoBuf

In general, the protocol buffer supports to store raw data. However, this fails currently. For example:

@Serializable class ProtoClass(@SerialId(id = 1) val value: ByteArray)

throws

kotlinx.serialization.SerializationException: Any type is not supported

Storing a ByteArray doesn't seem to be possible with the current Serializer api, is it? i.e. KOutput doesn't has a method to write a ByteArray.

Generator for .proto files based on serializable Kotlin classes

The idea is that you can have your Kotlin classes as your "master" code that conveniently declares your APIs and that you can analyze and refactor in IDE. Then, if you want your APIs to be used from other languages, you could generate a protobuf .proto files based on that and use them for other languages.

The design shall have at least two layers. On lower layer we need a format-agnostic way to traverse structure of serializable classes, that is ClassDesc shall contain the corresponding methods to make full reflection on the serial representation of classes possible. On the next layer, the format-specific code would be used. In this case, there shall be a tool that takes a set serializable classes (with an ability to scan a whole folder of compiled classes) and outputs a proto file.

Trying to parse any map with duplicate keys (sometimes) results in a non-helpful exception

Let's take the following code:

@Serializable
data class WrappedMap(val mp: Map<String, Int>)
...
println(run<WrappedMap>{ JSON.parse("""{"mp": { "x" : 23, "x" : 42, "y": 4 }}""") })

This results in a following exception:

Exception in thread "main" kotlinx.serialization.SerializationException: Elements should be in order, unexpected index 3
	at kotlinx.serialization.internal.ListLikeSerializer.load(CollectionSerializers.kt:74)
	at kotlinx.serialization.KInput.readSerializableValue(Serialization.kt:240)
	at kotlinx.serialization.ElementValueInput.readSerializableElementValue(Serialization.kt:402)
	at ru.spbstu.competition.WrappedMap$$serializer.load(Main.kt)
	at ru.spbstu.competition.WrappedMap$$serializer.load(Main.kt:73)
	at kotlinx.serialization.KInput.read(Serialization.kt:206)
	at kotlinx.serialization.json.JSON.parse(JSON.kt:46)
        <...my code...>

This is not specific to JSON and is somehow related to the way Maps are deserialized from any input type where duplicate keys are possible.

You should either be exact about whether you support duplicate keys in such formats or at least provide a better exception, 'cos this is not helpful at all. Even more, if you remove y from the data, it is parsed successfully with the value of x being 42.

`ClassCastException` in `kotlinx-serialization-runtime-js`

When trying run the following code in Kotlin-JS:

import kotlinx.serialization.json.JSON

data class Foo(val foo: String)

fun main(args: Array<String>) {
    println("Hello World!")
    println(JSON.stringify(Foo("Hey")))
}

I get this error:

kotlin.js:3289 Hello World!
kotlin.js:3446 Uncaught ClassCastException "Illegal cast"
"ClassCastException: Illegal cast
    at Object.throwCCE (file:///.../web/lib/kotlin.js:3446:13)
    at serializer (file:///.../web/lib/kotlinx-serialization-runtime-js.js:5499:91)
    at main (file:///.../web/main.js:42:37)
    at file:///D:/.../web/main.js:47:3
    at file:///D:/.../web/main.js:50:2"

(error message and stacktrace slightly edited for readability)

I tested this in both Firefox and Chrome. A repository to reproduce this bug: https://github.com/flaghacker/KotlinSerialBug, exact instructions in README.md.

Generic Data Structure Serialize / Deserialize

When parsing JSON, it is not always desirable, or required to map the parse result onto a custom data structure. There are many libraries (gson comes to mind), that allow the user to parse JSON data both to a custom data structure and a generic one. For instance:

    val input = "{}"
    val parser = JsonParser()
    val root = parser.parse(input)
    val prop = when (root) {
        is JsonObject -> root.get("prop")?.asString
        else -> null
    }

(yes i'm aware this is less than optimal kotlin code, but it illustrates the point, especially if you needed to do something different in the array case)

The current classes in kotlinx.serialization are focused on mapping to custom data structures.

A nice bonus of having this as part of the kotlinx.serialization package would be that it would be cross platform. Currently, as far as i can tell, there is no cross platform way of parsing JSON data. As a result, i'm using expect and actual for something that really could be platform agnostic.

Plugin crashes when @Transient annotation is used on fields without an initializer

I have a project configured to use kotlin serialization. The following code containing the @Transient annotation causes an exception in the gradle plugin.
Sample project replicating the issue can be downloaded here https://github.com/MFAshby/kotlin-serialization-bug. Run ./gradlew build to see the exception.

Sample code:

import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient

@Serializable
data class MySerializable(val name: String) {
    @Transient
    val someComputedProperty: String
        get() = name + "_stuff"
}

Exception:

Executing tasks: [:shared:compileJava, :app:generateDebugSources, :app:generateDebugAndroidTestSources, :app:mockableAndroidJar, :app:compileDebugAndroidTestSources, :app:compileDebugUnitTestSources, :app:compileDebugSources, :webapp:compileJava]

Configuration on demand is an incubating feature.
:shared:compileKotlin
Using Kotlin incremental compilation

e: java.lang.IllegalArgumentException: Argument for @NotNull parameter 'element' of org/jetbrains/kotlin/codegen/ExpressionCodegen.markStartLineNumber must not be null
at org.jetbrains.kotlin.codegen.ExpressionCodegen.$$$reportNull$$$0(ExpressionCodegen.java)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.markStartLineNumber(ExpressionCodegen.java)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:299)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:291)
at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:331)
at org.jetbrains.kotlin.codegen.MemberCodegen.initializeProperty(MemberCodegen.java:532)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl.doGenerateConstructorImpl(SerializableCodegenImpl.kt:153)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl.access$doGenerateConstructorImpl(SerializableCodegenImpl.kt:40)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl$generateInternalConstructor$1.invoke(SerializableCodegenImpl.kt:64)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl$generateInternalConstructor$1.invoke(SerializableCodegenImpl.kt:40)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.JVMCodegenUtilKt$generateMethod$1.doGenerateBody(JVMCodegenUtil.kt:109)
at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$CodegenBased.generateBody(FunctionGenerationStrategy.java:72)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:569)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:332)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:298)
at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:176)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.JVMCodegenUtilKt.generateMethod(JVMCodegenUtil.kt:106)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl.generateInternalConstructor(SerializableCodegenImpl.kt:64)
at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen.generateSyntheticInternalConstructor(SerializableCodegen.kt:39)
at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen.generate(SerializableCodegen.kt:33)
at org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl$Companion.generateSerializableExtensions(SerializableCodegenImpl.kt:51)
at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationCodegenExtension.generateClassSyntheticParts(SerializationCodegenExtension.kt:28)
at org.jetbrains.kotlin.codegen.ImplementationBodyCodegen.generateSyntheticPartsAfterBody(ImplementationBodyCodegen.java:384)
at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:148)
at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:319)
at org.jetbrains.kotlin.codegen.MemberCodegen.genClassOrObject(MemberCodegen.java:303)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassOrObject(PackageCodegenImpl.java:162)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateClassesAndObjectsInFile(PackageCodegenImpl.java:86)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateFile(PackageCodegenImpl.java:124)
at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:66)
at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.generatePackage(KotlinCodegenFacade.java:99)
at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:77)
at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:44)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:442)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:153)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:154)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:58)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:103)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:51)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:92)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:303)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:85)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:213)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:83)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.execIncrementalCompiler(CompileServiceImpl.kt:512)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$execIncrementalCompiler(CompileServiceImpl.kt:96)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:399)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:96)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:889)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:96)
at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:916)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:888)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:398)
at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

:shared:compileKotlin FAILED

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':shared:compileKotlin'.

Internal compiler error. See log for more details

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

  • Get more help at https://help.gradle.org

BUILD FAILED in 0s

1 actionable task: 1 executed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.