@@ -33,10 +33,15 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect
3333import com.fasterxml.jackson.annotation.JsonInclude
3434import com.fasterxml.jackson.annotation.JsonProperty
3535import com.fasterxml.jackson.annotation.PropertyAccessor
36+ import com.fasterxml.jackson.core.JsonGenerator
3637import com.fasterxml.jackson.databind.JsonNode
37- import com.fasterxml.jackson.databind.PropertyName
38+ import com.fasterxml.jackson.databind.ObjectMapper
39+ import com.fasterxml.jackson.databind.SerializerProvider
3840import com.fasterxml.jackson.databind.introspect.Annotated
3941import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
42+ import com.fasterxml.jackson.databind.ser.PropertyWriter
43+ import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter
44+ import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider
4045import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
4146import com.google.gson.JsonObject
4247import com.google.gson.JsonParser as GsonJsonParser
@@ -74,24 +79,40 @@ class IssueJsonConverter {
7479 }
7580 private val jiraBaseUrls: JiraBaseUrls = ComponentAccessor .getComponent(JiraBaseUrls ::class .java)
7681 private val uriBuilder: UriBuilder = UriBuilder .fromPath(jiraBaseUrls.restApi2BaseUrl())
77-
78- private val jacksonObjectMapper = jacksonObjectMapper().apply {
79- // we need to detect private fields, because some classes do not use public getters for JsonProperties
80- // See IssueRefJsonBean, which uses a modern fluent, no getter "data class" approach
82+ private val jacksonObjectMapper: ObjectMapper = jacksonObjectMapper().apply {
83+ setFilterProvider(
84+ SimpleFilterProvider ()
85+ .addFilter(" lp-only-json-property-filter" , OnlyAnnotatedFieldsFilter )
86+ .setFailOnUnknownId(false )
87+ )
88+ setAnnotationIntrospector(object : JacksonAnnotationIntrospector () {
89+ override fun findFilterId (a : Annotated ): Any = " lp-only-json-property-filter"
90+ })
8191 setVisibility(PropertyAccessor .FIELD , JsonAutoDetect .Visibility .ANY )
92+ }
8293
83- setAnnotationIntrospector(object : JacksonAnnotationIntrospector () {
84- override fun findNameForSerialization (a : Annotated ): PropertyName ? {
85- if (! a.hasAnnotation(JsonProperty ::class .java)
86- && ! a.hasAnnotation(JsonInclude ::class .java)
87- && ! a.hasAnnotation(javax.xml.bind.annotation.XmlElement ::class .java)
88- && ! a.hasAnnotation(javax.xml.bind.annotation.XmlAttribute ::class .java)
89- ) {
90- return null
91- }
92- return super .findNameForSerialization(a) ? : PropertyName .NO_NAME
94+ object OnlyAnnotatedFieldsFilter : SimpleBeanPropertyFilter() {
95+ override fun serializeAsField (
96+ pojo : Any? ,
97+ jgen : JsonGenerator ,
98+ provider : SerializerProvider ,
99+ writer : PropertyWriter
100+ ) {
101+ val annotations = writer.member?.allAnnotations?.annotations()
102+ ?.mapNotNull { it.annotationClass.qualifiedName }
103+ ? : emptyList()
104+
105+ val hasAnnotation = annotations.any {
106+ it == JsonProperty ::class .qualifiedName ||
107+ it == JsonInclude ::class .qualifiedName ||
108+ it.endsWith(" XmlElement" ) ||
109+ it.endsWith(" XmlAttribute" )
93110 }
94- })
111+
112+ if (hasAnnotation) {
113+ writer.serializeAsField(pojo, jgen, provider)
114+ }
115+ }
95116 }
96117
97118 @Throws(FieldException ::class )
@@ -107,8 +128,7 @@ class IssueJsonConverter {
107128 this .addAvailableNavigableFieldsToBean(issueBean, issue)
108129
109130 // Jackson is the official way now to serialize Beans. GSON will fail due to infinite loops in the model.
110- val jackson = jacksonObjectMapper
111- val jacksonJson: JsonNode = jackson.valueToTree(issueBean)
131+ val jacksonJson: JsonNode = jacksonObjectMapper.valueToTree(issueBean)
112132
113133 return GsonJsonParser .parseString(jacksonJson.toString()).asJsonObject // expose as GSON for API compatibility
114134 }
0 commit comments