1

I face the following problem : i have a class that has as data members java.util.Optional objects and i need to put transform that into a json. The code looks in a generic way like this:

public class MyClass{

  public java.util.Optional<MyCustomObject> object;

  public Myclass(java.util.Optional<MyCustomObject> object){
    this.object = object;
  }

  public java.util.Optional<MyCustomObject> getObject(){
    return this.object;
  }

  public void setObject(java.util.Optional<MyCustomObject> object){
    return this.object = object;
  }
}

When i turn this into a json i get something like this:

Optional[
                object
            ]

I want to get rid of that Optional part from the json. Could i do that?

Charles
  • 570
  • 11
  • 29
  • 1
    And what JSON library do you use? – fge Jan 29 '15 at 11:25
  • 1
    Pleas show your code for making the json from this. – Don Roby Jan 29 '15 at 11:25
  • 4
    Why are you wrapping the `MyCustomObject` into an `Optional` in the first place? Your use counteracts the intention of `Optional` completely as you are introducing another variable, `MyClass.object` which can be `null`… – Holger Jan 29 '15 at 11:29
  • 2
    If you're using Jackson, you could add a custom type converter for `Optional`, but Holger is right that Optional is redundant in the first place. – Marko Topolnik Jan 29 '15 at 11:43
  • 1
    Well it might be redundant, but this is the case that i have to deal with, if you say Jackson, then i'll have a look at that. – Charles Jan 29 '15 at 13:41
  • 1
    If you are using Gson [This Question](http://stackoverflow.com/questions/12161366/how-to-serialize-optionalt-classes-with-gson) might help. It appears to be using the Optional from Guava but the idea will be the same. I believe the redundant comment stems from the fact that you allow MyClass.object to be null. You should change the Ctor and setObject methods to take in MyCutsomObject instead of Optional then construct the Optional wrapper yourself. – Appak Jan 29 '15 at 17:53

1 Answers1

5

There are multiple Java libraries available for serialization/deserialization. One of these is the excellent Jackson library where you can tune your serialization in a fine grained way.

If you own the source code of the POJO MyClass you can simply add some annotations to get it to work properly.

If you assume that MyCustomObject looks like this:

public class MyCustomObject {
    private final String myVal;

    public MyCustomObject(String myVal) {
        this.myVal = myVal;
    }

    public String getMyVal() {
        return myVal;
    }
}

Then, your MyClass object can be declared like this (notice the annotations @JsonIgnore and @JsonProperty):

public class MyClass {
    private Optional<MyCustomObject> object;

    public MyClass(Optional<MyCustomObject> object) {
        this.object = object;
    }

    // Ignore the "normal" serialization
    @JsonIgnore
    public Optional<MyCustomObject> getObject() {
        return this.object;
    }

    public void setObject(Optional<MyCustomObject> object) {
        this.object = object;
    }

    // This handles the serialization
    @JsonProperty("object")
    private MyCustomObject getObjectAndYesThisIsAPrivateMethod() {
        return getObject().orElse(null);
    }
}

Finally, you can use the following code for serializing to JSON:

ObjectMapper mapper = new ObjectMapper();
final String json = mapper.writeValueAsString(
        new MyClass(Optional.ofNullable(new MyCustomObject("Yes, my value!"))));

The magic in the code above lies in the use of the ObjectMapper which handles the data binding i.e. converting between POJOs and JSON (and vice versa).


Another approach, if you do not own the source code of the MyClass class i.e. you can not modify it is to create a custom serializer as described in the Jackson docs.

wassgren
  • 18,651
  • 6
  • 63
  • 77