FasterXML / FasterXML/jackson-future-ideas

Different way to specify values for `Include.NON_DEFAULT` and `JsonInclude.Include.CUSTOM`

Aperta
#69 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Nessun dato sulla lingua
Stelle
21
Fork
3
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

I myself (and from the issues I read, a lot of other people too) have had trouble with `Include.NON_DEFAULT` due to the fact that it's not really possible to properly extract default values. There is `JsonInclude.Include.CUSTOM`, but that is pretty clunky to use in some cases.

It's been mentioned before that the possibility of changing or removing `Include.NON_DEFAULT` is being considered for jackson 3.x. I'd just like to propose one way to potentially solve this issue, which would be to change the ways `Include.NON_DEFAULT` and `Include.CUSTOM` obtain the default value/filter.

For this, I would propose two new annotations:
- `@JsonDefaultValue("PropertyName")`
- `@JsonIncludeFilter("PropertyName")`

For `Include.NON_DEFAULT`, jackson would try to find a static field annotated with a matching `@JsonDefaultValue` annotation, and then use that as the default value. This could be very nice to use, as you would only need to move your default values into separate static fields, and specifying a default value as a static property is a pretty reasonable and established pattern already.

For `Include.CUSTOM`, jackson would try to find a member function annotated with a matching `@JsonIncludeFilter` annotation, which returns a boolean, and then only include the value if that function returns true. Being a member function, this could be even more powerful than the existing behavior for `CUSTOM`, because it could have access to the entire object being serialized.

A usage example:

```kotlin
data class MyClass(
@JsonProperty("Prop1")
@JsonInclude(Include.NON_DEFAULT) // <- Jackson will look for a static @JsonDefaultValue field
val property1: String = default1,
@JsonProperty("Prop2")
@JsonInclude(Include.CUSTOM) // <- Jackson will look for a @JsonIncludeFilter method
val property2: String = default2,
@JsonProperty("Prop3")
val property3: String, // <- This property has no default - the class cannot be constructed to extract defaults
) {
@JsonIncludeFilter("Prop2") // <- The value will only be included if this returns 'true':
private fun shouldIncludeProperty2(): Boolean {
// Note how this has access to the whole object - I could also do something like 'property2 != property1'.
return property2.equals(default2, ignoreCase = true)
}

companion object {
@JvmStatic
@JsonDefaultValue("Prop1") // <- The value will only be included if it's not equal to the value of this property:
private val default1: String = "Hello"

@JvmStatic
private val default2: String = "World"
}
}
```

One potential issue with this is that it would probably be hard to use these in meta-annotations, since they explicitly include a property name. Perhaps it could be possible to omit the property name, in which case the default applies for the whole type:

```kotlin
data class Test(
val value: String
) {
companion object {
@JvmStatic
@JsonDefaultValue // <- no property name, this is the default value for anything with the type "Test"
val EMPTY = Test("")
}
}
```

I think the "static field/method that returns a default value" pattern is also already quite common, so this would integrate fairly well into most code bases.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.