1.2.2 capitalized property names replaced with lowercase
For capitalized property names, 1.2.1 generates properties with first lower-case letter and the rest is capitalized. 1.2.2 generates all-lower case property names. Is there a config option to control this behavior?
example:
1.2.1:
@JsonProperty("TU")
public TU tU;
1.2.2:
@JsonProperty("TU")
public Tu tu;
I'm quite surprised that this would change in 1.2.2 as I don't think there's any change that would cause it.
I can't replicate this myself when using 1.2.1 or 1.2.2. Do you have an example schema file or json snippet I can use?
This snippet of schema generates "sNM" in 1.2.1 and "snm" in 1.2.2. The code I used for generating pojos follows.
"SNM": {
"type": "object",
"properties": {
"Surname": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"Name": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"MiddleName": {
"type": "string"
}
},
"additionalProperties": false
},
import com.sun.codemodel.JCodeModel
import org.jsonschema2pojo.*
import org.jsonschema2pojo.rules.RuleFactory
import org.slf4j.LoggerFactory
import java.io.File
import java.net.URL
val log = LoggerFactory.getLogger("main")
private const val OUTPUT_DIR = "generated"
private const val PACKAGE = "ecp.schema.vs1"
fun main() {
val codeModel = JCodeModel()
val source: URL = CustomAnnotator::class.java.getResource("/schema/Vs1asci.json")!!
val config: GenerationConfig = object : DefaultGenerationConfig() {
override fun isGenerateBuilders(): Boolean { // set config option by overriding method
return false
}
override fun getAnnotationStyle(): AnnotationStyle {
return AnnotationStyle.NONE
}
override fun getCustomAnnotator(): Class<out Annotator> {
return CustomAnnotator::class.java
}
override fun isIncludeGetters(): Boolean {
return false
}
override fun isIncludeSetters(): Boolean {
return false
}
override fun isIncludeHashcodeAndEquals(): Boolean {
return false
}
override fun isIncludeToString(): Boolean {
return false
}
override fun isRemoveOldOutput(): Boolean {
return true
}
override fun getDateTimeType(): String {
return "java.util.Date"
}
override fun getDateType(): String {
return "java.util.Date"
}
override fun isIncludeAdditionalProperties(): Boolean {
return false
}
override fun isUseTitleAsClassname(): Boolean {
return false
}
override fun getPropertyWordDelimiters(): CharArray {
return charArrayOf()
}
}
val outputDir = File(OUTPUT_DIR)
log.info("generating {} in {}", PACKAGE, outputDir.absolutePath)
val mapper = SchemaMapper(RuleFactory(config, CustomAnnotator(), SchemaStore()), SchemaGenerator())
mapper.generate(codeModel, "ClassName", PACKAGE, source)
codeModel.build(outputDir)
}
package spu.ecp.json
import com.fasterxml.jackson.databind.JsonNode
import com.sun.codemodel.*
import org.codehaus.jackson.annotate.JsonCreator
import org.codehaus.jackson.annotate.JsonProperty
import org.codehaus.jackson.annotate.JsonValue
import org.jsonschema2pojo.AbstractAnnotator
import org.slf4j.Logger
import org.slf4j.LoggerFactory
class CustomAnnotator : AbstractAnnotator() {
override fun propertyField(field: JFieldVar, clazz: JDefinedClass, propertyName: String, propertyNode: JsonNode) {
// super.propertyField(field, clazz, propertyName, propertyNode);
log.debug("processing class: {} field: {} ", clazz.name(), field.name())
if (!isCollection(field.type())) {
field.annotate(javax.annotation.Nullable::class.java)
}
field.annotate(JsonProperty::class.java).param("value", propertyName)
(field.type() as? JDefinedClass)?.methods()?.forEach { method ->
when (method.name()) {
"toString" -> if (method.annotations().size < 2) {
method.annotate(JsonValue::class.java)
}
"fromValue" -> if (method.annotations().isEmpty()) {
method.annotate(JsonCreator::class.java)
}
}
}
}
fun isCollection(jType: JType): Boolean {
val typeName: String = jType.toString()
return typeName.contains("List") ||
typeName.contains("Set") ||
typeName.contains("Map") ||
typeName.contains("Collection")
}
companion object {
private val log: Logger = LoggerFactory.getLogger(CustomAnnotator::class.java)
}
}
plugins {
id 'org.jetbrains.kotlin.jvm' version '2.0.0'
}
group = 'spu.ecp.json'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.jsonschema2pojo:jsonschema2pojo-core:1.2.2'
implementation 'org.codehaus.jackson:jackson-core-asl:1.9.13'
implementation 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
implementation 'org.slf4j:slf4j-log4j12:1.7.30'
testImplementation 'org.jetbrains.kotlin:kotlin-test'
}
test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(8)
}
tasks.register('runMain', JavaExec) {
main = 'spu.ecp.json.MainKt'
classpath = sourceSets.main.runtimeClasspath
}
@joelittlejohn I believe it's related to this change https://github.com/joelittlejohn/jsonschema2pojo/commit/59209437761369030c7d8cbb229bc73ce9d698d4#diff-f97fbc485092d3203a6f40624b3e8b7ba87e1301365e67be8f12c0319a06a030L24-R24
- import org.apache.commons.lang3.text.WordUtils;
+ import org.apache.commons.text.WordUtils;
The org.apache.commons.lang3.text.WordUtils has following implementation:
public static String capitalizeFully(String str, final char... delimiters) {
final int delimLen = delimiters == null ? -1 : delimiters.length;
if (StringUtils.isEmpty(str) || delimLen == 0) {
return str;
}
str = str.toLowerCase();
return capitalize(str, delimiters);
}
whereas org.apache.commons.text.WordUtils following:
public static String capitalizeFully(String str, final char... delimiters) {
if (StringUtils.isEmpty(str)) {
return str;
}
str = str.toLowerCase();
return capitalize(str, delimiters);
}
Note how latter is no longer doing bailout when delimiters length is 0 (which it is in given case as per configuration provided by @shme7ev).
I would leave the decision as to fix this on jsonschema2pojo side, report a bug to commons-text/commons-lang maintainers and wait for them to fix or leave it as it is up to you.
Update: it looks like given behavioral change was a deliberate decision taken by commons-text
maintainers (see TEXT-88).