Java 14 records with org.json

Viewed 143

I wanted to make new JSON object with org.json library, but I have noticed there is a problem with Java 14 records.

When I call

String json = new JSONObject(new Order("", "Albert", "GOOGL", "SELL", 97.9, 90L)).toString();

the fields are null.

I suppose it is because java record doesn't use old getters like getXYZ?

Is there a simple work around? I mean without using different library. Or maybe my assumptions are incorrect.

public record Order(
    String id,
    String userId,
    String securityId,
    String type,
    Double price,
    Long quantity
) {
}

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20220320</version>
</dependency>
2 Answers

If you don't want to use other libraries like Jackson or Gson (it will be a much better solution in my opinion) you could write your own converter:

public final class JsonConverter {

    private JsonConverter() {
    }
    
    @SneakyThrows
    public static String toJSON(Object object) {
        Class<?> c = object.getClass();
        JSONObject jsonObject = new JSONObject();
        for (Field field : c.getDeclaredFields()) {
            field.setAccessible(true);
            String name = field.getName();
            Object value = field.get(object);
            jsonObject.put(name, value);
        }
        return jsonObject.toString();
    }
}

You could use it like:

public static void main(String[] args) {
    Order order = new Order("", "Albert", "GOOGL", "SELL", 97.9, 90L);
    System.out.println(order);

    JSONObject jsonObject = new JSONObject(order);
    System.out.println(jsonObject.toString());

    System.out.println(JsonConverter.toJSON(order));
}

Output:

OrderRecord[id=, userId=Albert, securityId=GOOGL, type=SELL, price=97.9, quantity=90]
{}
{"quantity":90,"price":97.9,"securityId":"GOOGL","id":"","type":"SELL","userId":"Albert"}

It is a real workaround. However, it uses exactly org.json.

According to documentation JSONObject(Object bean) constructor

construct a JSONObject from an Object using bean getters.

So, yes as you noticed it expects getter to be in format getFieldName(), but in records getters are named differently.

For, example getter for filed price would be price(), not getPrice().

One possible solution is to add getters in record class, like this :

   public record Order(
            String id,
            String userId,
            String securityId,
            String type,
            Double price,
            Long quantity
    ) {
    
    
        public Double getPrice() { // Compliant
            return price;
        }
    
        public String getId() { // Compliant
            return id;
        }
    
        public String getSecurityId() { // Compliant
            return securityId;
        }
    
        public String getType() { // Compliant
            return type;
        }
    
        public Long getQuantity() { // Compliant
            return quantity;
        }
    }

You should see output like this :

enter image description here

Related