SnG
SnG

Reputation: 402

Using Jackson's ObjectMapper inside Custom Class

I have a class such as:

@Data
public class Lmao {
   String lol;
   String lel;

   public String getJsonString() throws Exception {
       ObjectMapper objectMapper = new ObjectMapper();
       return objectMapper.writeValueAsString(this);
   }
}

However, when I invoke the getJsonString() method, I get the following error:

java.lang.StackOverflowError
    at com.fasterxml.jackson.databind.introspect.AnnotatedClass._findFields(AnnotatedClass.java:795)
    at com.fasterxml.jackson.databind.introspect.AnnotatedClass._findFields(AnnotatedClass.java:802)
    at com.fasterxml.jackson.databind.introspect.AnnotatedClass.resolveFields(AnnotatedClass.java:571)
    at com.fasterxml.jackson.databind.introspect.AnnotatedClass.fields(AnnotatedClass.java:353)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addFields(POJOPropertiesCollector.java:350)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:283)
    at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getJsonValueMethod(POJOPropertiesCollector.java:169)
    at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findJsonValueMethod(BasicBeanDescription.java:223)
    at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByAnnotations(BasicSerializerFactory.java:349)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:208)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:157)
    at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1215)
    at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1167)
    at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:490)
    at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:688)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:107)
    at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3613)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:2980)

Is there anyway I can call Jackson's ObjectMapper inside the class itself so that I can better tie in the Json String with the object itself?

Edit: I forgot to mention that I am using lombok's data here, so the setters and getters for each individual property isnt needed.

Upvotes: 1

Views: 1727

Answers (3)

devops
devops

Reputation: 9197

rename your getJsonString() to toJsonString().

ObjectMapper thinks there is an property jsonStringin your bean. It try to call it via getter. This results in endless call.

Upvotes: 1

Darshan Mehta
Darshan Mehta

Reputation: 30849

You need to do the following:

  • Write getter and setters
  • Annotate getJsonString with @JsonIgnore

Below should work:

public class Test {

    String lol;
    String lel;

    @JsonIgnore
    public String getJsonString() throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(this);
    }

    public String getLol() {
        return lol;
    }


    public void setLol(String lol) {
        this.lol = lol;
    }


    public String getLel() {
        return lel;
    }


    public void setLel(String lel) {
        this.lel = lel;
    }

    public static void main(String[] args) throws Exception{
        Test t = new Test();
        System.out.println(t.getJsonString());
    }
}

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 692131

Sure, but you need to make it ignore the jsonString property, to avoid that endless recursive call. Add @JsonIgnore to the getter. Or name your method so that it isn't a property anymore, like for example toJson() (which is also a better name, IMO).

That said, creating a new ObjectMapper everytime is not a good idea. You should instead alsays reuse the same one, constructed once and for all.

Upvotes: 2

Related Questions