javajsonjacksonebean

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Symbol"


I am trying to take some JSON that looks like this (from AlphaVantage):

{
    "Symbol": "IBM",
    "AssetType": "Common Stock",
    "Name": "International Business Machines Corporation",
... more properties
}

And parse it using Jackson (& Ebeans):

  ObjectMapper objectMapper = new ObjectMapper();
  String json = response.body().string();
  Stock stock = objectMapper.readValue(json, Stock.class);
  stock.save();

My Stock class looks like this:

@Entity
@Table(name = "stock")
public class Stock extends Model {

@Id
private Long id;
private String Symbol;
private String AssetType;
private String Name;
... other properties

public Long getId() {
    return this.id;
}

public void setId(Long id) {
    this.id = id;
}

public String getSymbol() {
    return this.Symbol;
}
public void setSymbol(String Symbol) {
    this.Symbol = Symbol;
}

... other setters/getters

}

Instead I am getting the following error:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Symbol" (class com.myprojectname.Stock), not marked as ignorable (60 known properties: "ebitda", "sharesOutstanding", "bookValue", ....more fields

Why is Jackson having a problem connecting to my Stock class? How do I connect Symbol from the JSON into Symbol in the Stock class?

EDIT: I get the same error message if I change symbol to lowercase:

@Entity
@Table(name = "stock")
public class Stock extends Model {

@Id
private Long id;
private String symbol;

public String getSymbol() {
    return this.symbol;
 }
public void setSymbol(String symbol) {
    this.symbol = symbol;
 }
}

Solution

  • Changing the name of the property from Symbol to symbol won't help since we still have the "Symbol" in the json file.

    You can try to use the @JsonProperty annotation like in the example. For the "Symbol" json field it can look like this:

    //...
        private String Symbol;
    
        @JsonProperty("Symbol")
        public String getSymbol() {
            return this.Symbol;
        }
    
        @JsonProperty("Symbol")
        public void setSymbol(String symbol) {
            this.Symbol = symbol;
        }
    // ...
    

    This approach should also work for other fields which differ from the json counterpart by the uppercase / lowercase letter.

    edit: Just like in the answer from the question linked in my comment above - paraphrasing it:

    Since your setter method is named setSymbol() Jackson assumes the variable is named symbol because of the Java naming conventions (variables should start with lower case letters).

    edit(2): Other option would be leveraging the object mapper configuration. So instead of the annotations approach you could use the approach from here and make the mapper case insensitive:

    objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
    

    Other property I find useful is:

    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    

    described in the Baeldung's article linked above