20

I have an ArrayList of a class that looks like this:

public class Person {
    String name;
    String age 
    List<String> education = new ArrayList<String> ();
    List<String> family = new ArrayList<String> (); 
    List<String> previousjobs = new ArrayList<String>(); 
}

I want to write this list as Json and tried this code:

Writer out = new PrintWriter("./test.json");
mapper.writerWithDefaultPrettyPrinter().writeValueas(out, persons);

and got this error message:

No serializer found for class ~~~~~~ and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0])`

I tried adding mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) but it made all the Person Objects empty for some unknown reasons.

What am I getting wrong?

9
  • I have an arraylist called persons. When I do mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS), it gives me [ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { } ]. Without it, it just creates a broken json file: " [".
    – 7029279
    Commented Jan 3, 2020 at 12:43
  • Can you put the full code. Commented Jan 3, 2020 at 12:43
  • 3
    My code is very messy as I am new to Java. I am scraping Wikipedia and collecting data of politicians.
    – 7029279
    Commented Jan 3, 2020 at 12:48
  • 1
    The sample you've posted has no public members. It's likely that the serializing class simply can't see anything in those objects to serialize. Commented Jan 3, 2020 at 14:15
  • 1
    Java's default access modifier (which is what you get if you don't specify something else, as you've done here) only allows access within the same package or from the class itself. The best practice is to add (public) getters and setters. Commented Jan 3, 2020 at 21:41

4 Answers 4

30

Excerpt from here:

By default, Jackson 2 will only work with with fields that are either public, or have a public getter methods – serializing an entity that has all fields private or package private will fail:

Your Person has all fields package protected and without getters thus the error message. Disabling the message naturally does not fix the problem since the class is still empty from Jackson's point of view. That is why you see empty objects and it is better to leave the error on.

You need to either make all fields public, like:

public class Person {
    public String name;
    // rest of the stuff...
}

or create a public getter for each field (and preferably also set fields private), like:

public class Person {
    private String name;

    public String getName() {
        return this.name;
    }
    // rest of the stuff...
}
3
  • Great answer. To add a small postscript: For large classes with lots of fields, Eclipse has an auto-generate getters and setters feature, found under Source -> Generate Getters and Setters Commented Apr 13, 2021 at 6:28
  • 2
    @Lycanthropeus Yes, that is one way. I prefer using Lombok @Getter @Setter annotations to have cleaner code.
    – pirho
    Commented Apr 13, 2021 at 15:15
  • Thanks. My field was not having any public access. Missed lombok @Data which add getter, setter Commented Jan 21, 2022 at 8:21
2

create object of object mapper class and pass below property to resolve this issue in:

given().body(value).when().post("/workspaces").then().spec(responseSpecification).log().all();  

String value = objectMapper.writeValueAsString(workspaceRoot);

ObjectMapper objectMapper = new ObjectMapper()               .setVisibility(PropertyAccessor.FIELD,JsonAutoDetect.Visibility.ANY).disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
0

All the fields in Person class are with default access specifier.Either make the fields public or add public getter methods.Below class should work.

public class Person {

    private String name;
    private String age ;
    private List<String> education = new ArrayList<String> ();
    private List<String> family = new ArrayList<String> (); 
    private List<String> previousjobs = new ArrayList<String>(); 

    public String getName() {
        return name;
    }

    public String getAge() {
        return age;
    }

    public List<String> getEducation() {
        return education;
    }

    public List<String> getFamily() {
        return family;
    }

    public List<String> getPreviousjobs() {
        return previousjobs;
    }

}

If POJO is in our control we can modify POJO as above.If POJO is not under control we can set the visibility to any as below objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

0

With Lombok Builder you can avoid this with Getter annotation, your class will look like;

@Builder
@Getter
public class Person {
    String name;
    String age 
    List<String> education = new ArrayList<String> ();
    List<String> family = new ArrayList<String> (); 
    List<String> previousjobs = new ArrayList<String>(); 
}

You would have to build a person with the Lombok builder but the writer will have access to all person values

Not the answer you're looking for? Browse other questions tagged or ask your own question.