FasterXML / jackson-annotations

Core annotations (annotations that only depend on jackson-core) for Jackson data processor
https://github.com/FasterXML/jackson
Apache License 2.0
1.03k stars 330 forks source link

@jsonignore annotation by way of mixin only working on field, but not get/set methods for jaxb generated classes #5

Closed matthewshannon closed 12 years ago

matthewshannon commented 12 years ago

See: http://markmail.org/message/4x2lj6fgikrv4vb4

I have a simple xml schema

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
    targetNamespace="http://xmlns.test.com/test" xmlns:test="http://xmlns.test.com/test">

    <xs:element name="Pod">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="username" type="xs:string"/>
                <xs:element name="password" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

that I invoke the xjc tool to generate the following class:

package com.test.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "username",
    "password"
})
@XmlRootElement(name = "Pod")
public class Pod {

    @XmlElement(required = true)
    protected String username;
    @XmlElement(required = true)
    protected String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String value) {
        this.username = value;
    }
    public String getPassword() {
        return password;
    }

    public void setPassword(String value) {
        this.password = value;
    }

}

I'm trying to utilize the mixin functionality to prevent the getPassword method from serializing by way of an @JsonIgnore.

http://fasterxml.github.com/jackson-annotations/javadoc/2.0.6/com/fasterxml/jackson/annotation/JsonIgnore.html

I have found that the mixin only seems to work when the @JsonIgnore property is applied on the password field,

@JsonIgnore protected String password;

but does nothing when set on the method itself

@JsonIgnore abstract public String getPassword();

As I ultimately want to allow setPassword, but not getPassword, it does not make sense to put the @JsonIgnore on the field. Thus I need to get it working on the getPassword method. Reading the javadoc, I understand that I eventually will need to also utilize the @JsonProperty annotation on the setter due to change in behaviour of how @JsonIgnore works. But what I'm seeing is that @JsonIgnore is not working for anything but the field in the first place.

Any ideas what could be going on? Is this likely a bug, or have I messed up? I'm utilizing jackson 2.0.6.

package com.test.model;

import com.fasterxml.jackson.annotation.JsonIgnore;

abstract class PodMixIn
{
  // @JsonIgnore protected String password;
  @JsonIgnore abstract public String getPassword();
  // @JsonIgnore abstract public void setPassword(String value);
}

I have uploaded a fully self-contained test case that demonstrates the issue at: https://docs.google.com/open?id=0Bxy6NL7ud-h6Wjg3MTl5WF9rbUk

cowtowncoder commented 12 years ago

Quick verification: it looks like you are using JAXB annotations, along with Jackson's @JsonIgnore? JAXB annotation handling is quite a bit customized, due to JAXB semantic differences from Jackson ones (JAXB uses package annotations, for example; does not necessarily support annotation inheritance). So this may be causing the issues.

cowtowncoder commented 12 years ago

Reading through above again, I think this would apply to Jackson annotation use case as well. With Jackson 1.9 and above, annotations for a logical property are combined, and what happens then is roughly as follows:

Now, with JAXB annotations, @XmlElement is equivalent to @JsonProperty, making field visible for serialization. So you will need to add a mix-in for it anyway.

This also explains behavior you are seeing: since you @JsonIgnore has higher precedence than @XmlElement, it means that mix-in for field will make the whole property disappear; whereas adding it to getter will cause a "split property" case, but field is still used for access.

Of course, if there was a way to change xjc not to add @XmlElement to fields but to getter, that would also resolve the issue. But as things are, I think you do need to add couple more "extra" annotations to make things fit together.