jnosql icon indicating copy to clipboard operation
jnosql copied to clipboard

Align Jakarta NoSQL and Jakarta JSON Binding supported types.

Open redmitry opened this issue 3 years ago • 3 comments

Hello,

I am interested in using jnosql Java classes as a jsonb ones to be directly used by JAX-RS endpoints. Both uses similar ways to provide additional types support (adapter / converter). Is there any chance to add complete JSON-B types support into the jNoSQL? For instance, currently, I have to provide my own "reader" for JsonObject type, as we have schema-less metadata in our mongodb model which can be any arbitrary json. In JSON Binding I just put JsonObject property, but for the NoSQL I have to convert "Document" to the JsonObject, which is not a big deal, but there are other "jsonb" types like "long[]", etc. that are supported by jsonb and not by NoSQL.

Cheers,

D.

P.S. https://jakarta.ee/specifications/jsonb/3.0/jakarta-jsonb-spec-3.0.html#default-mapping

redmitry avatar Apr 25 '22 08:04 redmitry

Hello @redmitry How are you? Yes, we're looking for it. Could you put more details about it?

We could create some methods to return because the DocumentEntity at the end is a Map<String, Object>. So, what we could do is:

DocumentEntity entity =....
JsonObject json = entity.toJson();

otaviojava avatar Apr 25 '22 10:04 otaviojava

Hello Octávio, I use the Reader(s) and service loader. Here is my code for the JsonObject:

public class JsonObjectTypeReferenceReader implements TypeReferenceReader {

    @Override
    public boolean test(TypeSupplier<?> typeReference) {
        return JsonObject.class.equals(typeReference.get());
    }

    @Override
    public <T> T convert(TypeSupplier<T> typeReference, Object obj) {
        if (Iterable.class.isInstance(obj)) {
            JsonObjectBuilder builder = Json.createObjectBuilder();
            Iterator<Document> iter = Iterable.class.cast(obj).iterator();
            while (iter.hasNext()) {
                final Document doc = iter.next();
                final String name = doc.getName();
                final Object value = doc.get();
                if (List.class.isInstance(value)) {
                    final List list = List.class.cast(value);
                    if (list.isEmpty()) {
                        builder.add(name, Json.createObjectBuilder().build());
                    } else if (list.size() > 1) {
                        final JsonArrayBuilder ab = Json.createArrayBuilder();
                        for (Object elem : list) {
                            ab.add(getJsonValue(elem));
                        }
                        builder.add(name, ab);
                    } else {
                        final Object o = list.get(0);
                        if (List.class.isInstance(o)) {
                            final JsonObject array = (JsonObject)convert(typeReference, List.class.cast(o));
                            builder.add(name, Json.createArrayBuilder().add(Json.createObjectBuilder(array)));
                        } else {
                            builder.add(name, (JsonObject)convert(typeReference, list));
                        }
                    }
                } else {
                   builder.add(name, getJsonValue(value)); 
                }
            }
            return (T)builder.build();
        }
        return null;
    }
    
    private JsonValue getJsonValue(Object value) {
        if (value == null) {
            return JsonValue.NULL;
        } else if (value instanceof String) {
            return Json.createValue(value.toString());
        } else if (value instanceof Double) {
            return Json.createValue(Double.class.cast(value));
        } else if (value instanceof Long) {
            return Json.createValue(Long.class.cast(value));
        } else if (value instanceof Integer) {
            return Json.createValue(Integer.class.cast(value));
        } else if (value instanceof Boolean) {
            return Boolean.class.cast(value) ? JsonValue.TRUE : JsonValue.FALSE;
        }
        return null;
    }
}

I know that probably it is more a hack, but it works for me...

Probably there could be a fast-lane for the document drivers, instead of bson -> nosql -> json, make bson -> json, but again there is no standard convertor from bson to javax.json (or jakarta.json?).

Cheers,

D.

redmitry avatar Apr 25 '22 10:04 redmitry

Right now, AFIK there is no standard convertor between bson to javax.json. But it is a good discussion to have between the specs.

otaviojava avatar Apr 25 '22 10:04 otaviojava

This issue aims to move @redmitry's code and create a test for it.

otaviojava avatar Jan 18 '23 17:01 otaviojava

Hi, The latest code is: https://gitlab.bsc.es/inb/ga4gh/beacon-v2-bsc/-/blob/master/beacon-nosql-model/src/main/java/es/bsc/inb/ga4gh/beacon/nosql/value/JsonObjectTypeReferenceReader.java

redmitry avatar Jan 18 '23 20:01 redmitry

Thank you

otaviojava avatar Jan 21 '23 16:01 otaviojava