dsl-json icon indicating copy to clipboard operation
dsl-json copied to clipboard

@JsonAttribute(ignore = true) is ignored for fields in kotlin classes

Open runaloop opened this issue 5 years ago • 4 comments

Faced with such a problem, I have 2 classes, one written in java, and one in a kotlin:

@CompiledJson
class KotlinClassWithIgnore(val name: String = "Kotlin", @JsonAttribute(ignore = true) val ignored: String = "IGNORED")

@CompiledJson
static class JavaClassWithIgnore {
    public String name = "JAVA";
    @JsonAttribute(ignore = true)
    public String ignored = "IGNORED";
}

If I serialize kotlin class, to a string, I always see "ignored" field in it. To serialize I use this code:

DSL.JSON().serialize(KotlinClassWithIgnore(), PrettifyOutputStream(os))
println(os)
os.reset()
DSL.JSON().serialize(JavaClassWithIgnore(), PrettifyOutputStream(os))
println(os)

And I got this result:

I/System.out: {
I/System.out:   "name": "Kotlin",
I/System.out:   "ignored": "IGNORED"
I/System.out: }
I/System.out: {
I/System.out:   "name": "JAVA"
I/System.out: }

The question is how to make @JsonAttribute(ignore = true) field in kotlin class to be ignored by DSL-JSON?

runaloop avatar Jan 18 '20 05:01 runaloop

It would be great if there was a Kotlin test project where such examples could be tested and verified but I have not yet found to setup such a project via Maven. I guess I could set it up via gradle, but I'd much prefer to have it in Maven so all tests can run at once.

Anyway, can you write relevant Java class like this: https://github.com/ngs-doo/dsl-json/blob/8783d39fd20ce609eccdd37c932565a6b83ba123/tests-java8/src/test/java/com/dslplatform/json/JsonObjectTest.java#L70 and make a PR which shows the issue (there is some generated code which shows the exact Java output for the Kotlin model, thats how I extracted those examples). I can take a look then on how to resolve it [although it's possible you'll figure out how to resolve it when you write such a test :) ]

zapov avatar Jan 18 '20 10:01 zapov

Thank you for your answer. I tried to import maven project - tests-java8, and created a kotlin test in it, to run it, I have to add these lines to pom.xml:

--- dependencies: 
<dependency>
			<groupId>org.jetbrains.kotlin</groupId>
			<artifactId>kotlin-stdlib</artifactId>
			<version>${kotlin.version}</version>
		</dependency>
---plugins:
			<plugin>
				<groupId>org.jetbrains.kotlin</groupId>
				<artifactId>kotlin-maven-plugin</artifactId>
				<version>${kotlin.version}</version>

				<executions>
					<execution>
						<id>test-kapt</id>
						<goals>
							<goal>test-kapt</goal>
						</goals>
						<configuration>
							<sourceDirs>
								<sourceDir>src/test/kotlin</sourceDir>
								<sourceDir>src/test/java</sourceDir>
							</sourceDirs>
							<annotationProcessorPaths>
								<annotationProcessorPath>
									<groupId>com.dslplatform</groupId>
									<artifactId>dsl-json-java8</artifactId>
									<version>1.9.5</version>
								</annotationProcessorPath>
							</annotationProcessorPaths>
						</configuration>
					</execution>


					<execution>
						<id>compile</id>
						<goals> <goal>compile</goal> </goals>
						<configuration>
							<sourceDirs>
								<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
								<sourceDir>${project.basedir}/src/main/java</sourceDir>
							</sourceDirs>
						</configuration>
					</execution>
					<execution>
						<id>test-compile</id>
						<goals> <goal>test-compile</goal> </goals>
						<configuration>
							<sourceDirs>
								<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
								<sourceDir>${project.basedir}/src/test/java</sourceDir>
							</sourceDirs>
						</configuration>
					</execution>
				</executions>
			</plugin>

Kotlin class looks like:

package com.dslplatform.json

@CompiledJson
data class AKotlinModel(val someString: String, @JsonAttribute(ignore = true)val paramWithIgnoreFlag: Boolean) {

    @JsonAttribute(ignore = true)
    lateinit var stringFieldWithIgnoreFlag: String
    @JsonAttribute(mandatory = true)
    lateinit var stringWhichShouldBeInPlace: String
}

And Kotlin test looks like:

package com.dslplatform.json

import com.dslplatform.json.runtime.Settings
import org.junit.Assert
import org.junit.Test
import java.io.ByteArrayOutputStream




class KotlinClassesTest{
    val dslJson = DslJson(Settings.withRuntime<Any>().includeServiceLoader().allowArrayFormat(true))
    @Test
    fun `Field with JsonAttribute(ignore = true) flag, must not be included to result string`() {
        val model = AKotlinModel("someStr", true)
        model.stringFieldWithIgnoreFlag = "this string is ignored"
        model.stringWhichShouldBeInPlace = "this string should be in json"
        val os = ByteArrayOutputStream()
        dslJson.serialize(model, os)
        Assert.assertEquals("{\"someString\" : \"someStr\", \"stringWhichShouldBeInPlace\" : \"this string should be in json\"}", os.toString())
    }
}

This test is red for now with this output:

org.junit.ComparisonFailure: 
Expected :{"someString" : "someStr", "stringWhichShouldBeInPlace" : "this string should be in json"}
Actual   :{"stringFieldWithIgnoreFlag":"this string is ignored","paramWithIgnoreFlag":true}

And I have no idea, why my output JSON string has some of the fields and doesn't have others. Any thoughts on how to deal with it?

runaloop avatar Jan 20 '20 13:01 runaloop

I tried setting up java8 test project like that but it didn't do annotation processing on Kotlin at all.

So I setup a separate project which is somewhat better but still fails to compile for some probably trivial reasons (it creates output in generated-sources instead of generated-test-sources)

If you can help out with fixing that project so it starts compiling that would be great: https://github.com/ngs-doo/dsl-json/commit/2db2de51d424a82be77634f23b81c2f6798445d9

As for the ignore thing, DSL-JSON still does not support defaults on arguments, although you can simulate that with empty ctors in which case defaults are preserved. The model you provided for tests is missing those defaults so it doesn't compile, but I'll look whats going on when test project starts running.

zapov avatar Feb 17 '20 09:02 zapov

FWIW this test is now in, although commented out: https://github.com/ngs-doo/dsl-json/blob/master/tests-kotlin/src/main/kotlin/com/dslplatform/json/ModelWithIgnore.kt#L17

I have some questions though:

  • to be able to pass the default in, need to figure out where Kotlin defines this default
  • not sure what is expected to do when there is no default... the other use case looks like a bad requirement

zapov avatar Oct 08 '20 07:10 zapov