dardy dardy - 1 month ago 10
Java Question

Why does Predicates.instanceOf returns false?

I have a

String s =
{
"code1" : {
"price" : 100,
"type" : null
},
"code2" : {
"price" : 110,
"type" : null
}
}


Then I do:

Object p = Mapper.readValue(s, Person.class);


So it executes the method annotated with
@JsonCreator
in
Person.class
:

@JsonCreator
static Person create(Map<String, Object> s) {
s = Maps.filterValues(s, Predicates.instanceOf(Person.class));
...
}


My problem is
s
is always empty. I checked and the values have a
price
and a
type
. But when I do
ps.get("code1").getClass()
, it gives me
LinkedHashMap
.

I don't understand what is happening... Do you have any clue?

This is my class
Person
(it's an inner class):

public static class Person{

private int price;
private String type;
public Person(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
public String getType() {
return type;
}
}


Thanks!

Answer

The problem is that you are deserializing json String to Object and you will always have LinkedHashMap there, because java.lang.Object doesn't have any custom field.

Just try a different way:

  public  class Demo {
        public static void main(String[] args) throws IOException {
            String s = "{" +
                    "  \"code1\" : {" +
                    "    \"price\" : 100," +
                    "    \"type\" : null" +
                    "  }," +
                    "  \"code3\" : {" +
                    "    \"somethingElsse\" : false," +
                    "    \"otherType\" : 1" +
                    "  }," +
                    "  \"code2\" : {" +
                    "    \"price\" : 110," +
                    "    \"type\" : null" +
                    "  }" +
                    "}";


            ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            Map<String, Person> mapPerson = mapper.readValue(s, MapPerson.class);

            Map<String, Person> filteredMap = Maps.filterValues(mapPerson, new Predicate<Person>() {
                @Override
                public boolean apply(Person person) {
                    return person.isNotEmpty();
                }
            });

            System.out.println(filteredMap);


        }

        public static class MapPerson extends HashMap<String, Person> {}

        public static class Person{

            private int price;
            private String type;

            public Person() {
            }

            public boolean isNotEmpty() {
                return !(0 == price && null ==type);
            }

            @Override
            public String toString() {
                return "Person{" +
                        "price=" + price +
                        ", type='" + type + '\'' +
                        '}';
            }

            public int getPrice() {
                return price;
            }

            public void setPrice(int price) {
                this.price = price;
            }

            public String getType() {
                return type;
            }

            public void setType(String type) {
                this.type = type;
            }
        }
    }

When you configure your objec mapper with configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) it will just add an empty instance of Person to your map instead of throwing an exception. So you should also define a method that will answer if an instance of Person is empty and then filter your map using it.

If you use java 8 you can have a less code when you filter the map:

Map<String, Person> filteredMap = Maps.filterValues(mapPerson, Person::isNotEmpty);

BTW, it will work wine even you have some extra fields inside key values fro you JSON:

 {
      "code1" : {
        "price" : 100,
        "type" : null,
        "uselessExtraField": "Hi Stack"
      },
      "code2" : {
        "price" : 110,
        "type" : null,
        "anotherAccidentalField": "What?"
      }
    }

You will have the same result as if that fields never existed.

Comments