eclipse / jnosql

Eclipse JNoSQL is a framework which has the goal to help Java developers to create Jakarta EE applications with NoSQL.
Other
231 stars 72 forks source link

Align Jakarta NoSQL and Jakarta JSON Binding supported types. #265

Closed redmitry closed 1 year ago

redmitry commented 2 years ago

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

otaviojava commented 2 years ago

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();
redmitry commented 2 years ago

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.

otaviojava commented 2 years ago

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 commented 1 year ago

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

redmitry commented 1 year ago

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

otaviojava commented 1 year ago

Thank you