jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

setter method interferes with (some) getter methods

Open Wolvinny opened this issue 1 year ago • 5 comments

Hello,

first of all, i'm not really that experienced with jackson, but I've been running into an issue and i see no way to solve it. So, i have a class named 'Member' (see code below). Each member has a name, color, displayname and much more (but this is unrelevant). Each of these can be get using getName(), getColor(), and getDisplayName(). Now, whenever i add the setName() function, it's not even being referenced in another class, the 'name' property will always return null. When i change the method name, like add a letter, or make it static, it'll work just fine. What also makes it works is adding a @JsonProperty annotation to the getter. Adding it to the String itself also doesnt do anything Now, this is also the case for the getColor(). I have tried adding JsonIgnore to the setter methods but this didn't work either Now, the weird part is that the getDisplayName() works fine even though it is the exact same structure.

I've asked for help from an experienced java developer, which also couldn't help me and i couldn't find anything on this issue. I'm kinda lost as of what to do

Version 2.13.3

Code:


   private String color;
   @JsonProperty("name") //doesnt do anything
   private String name;

    @JsonProperty("display_name")
    private String display_name;
    
    @JsonProperty("display_name") //this makes it work
   public String getName(){
        return name;
    }
   public String getColor(){
        return color;
    }
    public String getDisplayName(){
        return display_name;
    }
    
    
 @JsonIgnore
    public  void setName(String name){
        this.name = name;
    }
       @JsonIgnore
    public void setDisplayName(String name){
        this.display_name = name;
    }
    @JsonIgnore
    public void setColor (String color){
         this.color = color;
    }
    ```

Wolvinny avatar Aug 20 '22 22:08 Wolvinny

Going forward,the proper channel for usage questions; would be either mailing list:

https://groups.google.com/g/jackson-user

or Gitter chat:

https://gitter.im/FasterXML/jackson-databind

as issue tracker is meant for reporting bugs and requesting new features.

But since you have added all this information here I will try to help.

The problem here is that I don't know what the problem is. Interferes how? What you are you trying to do? Could you show a piece of code to explain the problem (unit test)?

cowtowncoder avatar Aug 21 '22 23:08 cowtowncoder

So, i'll use my full code to explain. Its mean for the Pluralkit api

package com.luwuna.PluralkitAPI.Models;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.luwuna.PluralkitAPI.Models.Privacy.MemberPrivacy;
import com.luwuna.PluralkitAPI.Models.Privacy.SystemPrivacy;
import com.luwuna.PluralkitAPI.PluralkitAPI;
import org.json.JSONObject;

import java.util.List;

import static com.luwuna.PluralkitAPI.PluralkitAPI.token;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Member {
    @JsonIgnore
    protected ObjectMapper mapper = new ObjectMapper();
    private String id;

    private String uuid;
    @JsonProperty("system") //for some reason it's not recognising the system variable, so I have to force it
    private String system;
    private String color;
     private String name;

    @JsonProperty("display_name")
    private String display_name;

    private String birthday;
    private String description;
    private String tag;
    private String pronouns;
    @JsonProperty("avatar_url")
    private String avatar_url;

    private String banner;


    private String created;
   // @JsonProperty("proxy_tags")
    private ProxyTag[] proxyTags;

    private MemberPrivacy privacy;
    @JsonProperty("keep_proxy")
    private boolean keepproxy;

     public Member(){}


    public String getId(){
        return id;
    }

    public String getUUID(){
        return uuid;
    }
    @JsonProperty("name") // will interfere if not present
    public String getName(){
        return name;
    }
    @JsonProperty("description")
    public String getDescription(){
        return description;
    }
    @JsonProperty("tag")
    public String getTag(){
        return tag;
    }
    @JsonProperty("pronouns")
    public String getPronouns(){
        return pronouns;
    }
    @JsonProperty("avatar_url")
    public String getAvatarUrl(){
        return avatar_url;
    }
    @JsonProperty("banner")
    public String getBanner(){
        return banner;
    }
  //  @JsonProperty("color")
    public String getColor(){
        return color;
    }
    @JsonProperty("created")
    public String getCreated(){
        return created;
    }

   @JsonProperty("display_name")
    public String getDisplayName(){
        return display_name;
    }
    @JsonProperty("proxy_tags")
    public ProxyTag[] getProxyTags(){
        return proxyTags;
    }
    @JsonProperty("birthday")
    public String getBirthday(){
        return birthday;
    }
    @JsonProperty("keep_proxy")
    public boolean hasKeepProxyEnabled(){
        return keepproxy;
    }
    @JsonProperty("system")
    public String getSystemId(){
        return system;
    }

    @JsonProperty("privacy")
    public MemberPrivacy getPrivacy(){
        return privacy;
    }

    @JsonIgnore
    public  void setName(String name){
        if(name.length() > 100) throw new IllegalArgumentException("A displayname must be less than 100 characters long!");
        this.name = name;
    }
   @JsonIgnore
    public void setDisplayName(String name){
        if(name.length() > 100) throw new IllegalArgumentException("A displayname must be less than 100 characters long!");
        this.display_name = name;
    }
    @JsonIgnore
    public void setColor (String color){
   //     if(hexColor.startsWith("#")) hexColor = hexColor.substring(1);
       // this.color = color;
    }


    @JsonIgnore
    public  void setBirthday(String birthday){
        if(!birthday.matches("^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$")){
            throw new IllegalArgumentException("A date must match the YYYY-MM-DD pattern!");
        }
        this.birthday = birthday;


    }
    @JsonIgnore
    public void setBirthday(String birthday, boolean hideYear){
        if(!birthday.matches("^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$")&&!hideYear) {
            throw new IllegalArgumentException("A date must match the YYYY-MM-DD pattern!");
        }
        if(!birthday.matches("^\\d{2}-(0[1-9]|[12][0-9]|3[01])$")&&hideYear){
            throw new IllegalArgumentException("A date must match the MM-DD pattern!");
        }
        if(hideYear){
            birthday = "0004-" + birthday; //Setting the year to 0004 hides the year
        }
        this.birthday = birthday;


    }
    @JsonIgnore
    public  void setAvatarUrl(String url){
        this.avatar_url = url;
    }
    @JsonIgnore
    public void setPronouns(String pronouns){
        this.pronouns = pronouns;
    }
    @JsonIgnore
    public void applyUpdates() {
        if(token==null) throw new IllegalArgumentException("You need a token to perform system changes!");
        PluralkitAPI api = new PluralkitAPI(token);
        try {
            String json = mapper.writeValueAsString(this);
            api.updateSystem(this.id, json);
        }catch (Exception e){
            e.printStackTrace();
        }

    }


}

As you can see, the getColor() method has an @JSONProperty() that is commented out. If i run it like this, the 'color' field will return null. If i add it, the color field will return its color. It does this with getName() aswell, but not with getAvatarUrl(). I have tried notating the initializations of the strings, to no avail Please note that i am very inexperienced with jackson so it might be a little messy

Wolvinny avatar Aug 24 '22 21:08 Wolvinny

@Wolvinny Unfortunately this is bit too big an example, but also lacking some necessary detail. I'd need a minimal version showing what is wrong. Not "xxx is null" kind of narrative but showing what JSON is read and what values are not expected. Ideally a unit test to show input, assertions of state.

Basically: if deserialization (read from JSON, set Java property) or serialization (write JSON from Java property) is behaving different from what you expect, outline that. Saying "color will return null" is not clear to me.

cowtowncoder avatar Aug 25 '22 00:08 cowtowncoder

The format of the JSONObect read from can be found here (i marked the property that gives issues), and the (simplified) object that returns is this

{
"id":"ccyvi",
"uuid":"5be75c0c-799f-4fe5-af15-933ade9516e4",
"system":"vspls",
"name":"Test", 
"display_name":"test",

"color":"00ff00",   //<-------

"birthday":"2000-01-01",
"pronouns":"she/they",
"avatar_url":"test.png",
"banner":null,
"description":null,
"created":"2022-08-20T12:17:07.675818Z"
}

The expected output of using System.out.println(.getColor()) is '00ff00', but is 'null' if not annotated with the @JsonProperty(). I marked the 'color" key, but this also happens with the 'name', 'pronouns' and 'display_name' keys.

Wolvinny avatar Sep 03 '22 20:09 Wolvinny

At this point I am not going to spend any time trying to piece together various disparate things: what is needed is an actual fully self-closed unit test with assertions. Not a textual description of this and that being done: but actual code that reads and writes json, with checks.

Labeling with need-test-case to denote that.

cowtowncoder avatar Sep 04 '22 00:09 cowtowncoder