@@ -29,7 +29,14 @@ import com.atlassian.jira.issue.fields.rest.json.beans.JiraBaseUrls
2929import com.atlassian.jira.rest.v2.issue.IncludedFields
3030import com.atlassian.jira.rest.v2.issue.IssueBean
3131import com.atlassian.jira.rest.v2.issue.builder.BeanBuilderFactory
32+ import com.fasterxml.jackson.annotation.JsonAutoDetect
33+ import com.fasterxml.jackson.annotation.JsonInclude
34+ import com.fasterxml.jackson.annotation.JsonProperty
35+ import com.fasterxml.jackson.annotation.PropertyAccessor
3236import com.fasterxml.jackson.databind.JsonNode
37+ import com.fasterxml.jackson.databind.PropertyName
38+ import com.fasterxml.jackson.databind.introspect.Annotated
39+ import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
3340import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
3441import com.google.gson.JsonObject
3542import com.google.gson.JsonParser as GsonJsonParser
@@ -68,6 +75,25 @@ class IssueJsonConverter {
6875 private val jiraBaseUrls: JiraBaseUrls = ComponentAccessor .getComponent(JiraBaseUrls ::class .java)
6976 private val uriBuilder: UriBuilder = UriBuilder .fromPath(jiraBaseUrls.restApi2BaseUrl())
7077
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
81+ setVisibility(PropertyAccessor .FIELD , JsonAutoDetect .Visibility .ANY )
82+
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
93+ }
94+ })
95+ }
96+
7197 @Throws(FieldException ::class )
7298 fun createJsonIssue (
7399 issue : Issue ,
@@ -81,7 +107,7 @@ class IssueJsonConverter {
81107 this .addAvailableNavigableFieldsToBean(issueBean, issue)
82108
83109 // Jackson is the official way now to serialize Beans. GSON will fail due to infinite loops in the model.
84- val jackson = jacksonObjectMapper()
110+ val jackson = jacksonObjectMapper
85111 val jacksonJson: JsonNode = jackson.valueToTree(issueBean)
86112
87113 return GsonJsonParser .parseString(jacksonJson.toString()).asJsonObject // expose as GSON for API compatibility
0 commit comments