0

I'm trying to serialise an object with a Long id to JSON, using Genson.

It works well if I serialise to JSON and back into Java. But I'm deserialising in JavaScript.

JavaScript can't support a full 64-bit unsigned int as a Number (I'm finding the last few bits of my id are being zeroed in JavaScript), so I need to convert the Long id to a String during serialisation.

I don't want to convert all the Longs in the Object, so I'm trying to use a Converter for just the id field.

import com.owlike.genson.annotation.JsonConverter;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;

...

/** the local database ID for this order */
@JsonConverter(LongToStringConverter.class)
@Id       
@Setter
@Getter
private Long id;

/** The unique ID provided by the client */
@Setter
@Getter
private Long clientKey; 

My converter code looks like this:

public class LongToStringConverter implements Converter<Long> {

    /** Default no-arg constructor required by Genson */
    public LongToStringConverter() {        
    }

    @Override
    public Long deserialize(ObjectReader reader, Context ctx) {
        return reader.valueAsLong();
    }

    @Override
    public void serialize(Long obj, ObjectWriter writer, Context ctx) {
        if (obj != null) {
            writer.writeString(obj.toString());
        }
    }
}

I'm not doing anything special when invoking serialisation itself:

    Genson genson = new GensonBuilder().useIndentation(true).create();
    String json = genson.serialize( order );

This doesn't work. Output still looks like this:

{
  "clientKey":9923001278,
  "id":1040012110000000002
}

What I'm trying to achieve is this:

{
  "clientKey":9923001278,
  "id":"1040012110000000002"   // value is quoted
}

I did also try to pass my Converter into a GensonBuilder but that hits all the Longs in the object, which isn't what I need.

Any advice?

Capn Sparrow
  • 2,030
  • 2
  • 15
  • 32
  • 1
    By default Genson uses getters/setters, so you would need to define this annotation on them. If you want to do ser/de using the class attributes and ignore get/set you can use something [like this](http://genson.io/Faq#how-to-change-the-default-visibility-of-fields-methods-and-constructors). – eugen Apr 18 '19 at 18:29
  • 1
    @eugen - thank you very much, works perfectly. I've updated my answer to reflect this information. – Capn Sparrow Apr 19 '19 at 10:46

1 Answers1

1

Well, I'm not clear on WHY but it looks like Genson just doesn't get presented with the annotation. It may be down to the use of Hibernate or Lombok.

The solution seems to be to force Genson to consider the annotated field.

I did this by using the GensonBuilder:

Genson genson = new GensonBuilder().useIndentation(true).include("id").create();
String json = genson.serialize( order );

EDIT: Incorporating Eugen's answer above, this also works because it instructs Genson to look at the private field instead of relying on the getter/setter:

Genson genson2 = new GensonBuilder().useFields(true, VisibilityFilter.PRIVATE).useMethods(true).create();
Capn Sparrow
  • 2,030
  • 2
  • 15
  • 32