-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RMB-1012: Enhance Database Efficiency by Eliminating Storage of Empty Values #1178
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some APIs don't use the object mapper, they directly pass on the JSON from the database to HTTP. Example with a record from mod-inventory-storage sample data:
Currently it returns
With this PR it returns
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,23 @@ | ||
package org.folio.dbschema; | ||
|
||
import com.fasterxml.jackson.annotation.JsonInclude; | ||
import com.fasterxml.jackson.databind.JsonDeserializer; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.introspect.ClassIntrospector; | ||
import com.fasterxml.jackson.databind.module.SimpleModule; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.util.Date; | ||
|
||
import org.folio.dbschema.util.DateDeserializer; | ||
import org.folio.dbschema.util.DateSerializer; | ||
|
||
/** | ||
* @author shale | ||
* | ||
*/ | ||
public final class ObjectMapperTool { | ||
private static final ObjectMapper DEFAULT_MAPPER = createDefaultMapper(); | ||
private static final ObjectMapper MAPPER = createDefaultMapper(); | ||
private static final ObjectMapper WRITE_MAPPER = createDefaultWriteMapper(); | ||
|
||
private ObjectMapperTool() { | ||
throw new UnsupportedOperationException("Cannot instantiate utility class."); | ||
|
@@ -31,6 +31,10 @@ public static ObjectMapper getMapper() { | |
return MAPPER; | ||
} | ||
|
||
public static ObjectMapper getWriteMapper() { | ||
return WRITE_MAPPER; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have the |
||
public static <M, D extends JsonDeserializer<M>> void registerDeserializer(Class<M> clazz, D deserializer) { | ||
SimpleModule module = new SimpleModule(); | ||
module.addDeserializer(clazz, deserializer); | ||
|
@@ -40,9 +44,9 @@ public static <M, D extends JsonDeserializer<M>> void registerDeserializer(Class | |
/** | ||
* Map (deserialize) JSON String to java type instance. | ||
* | ||
* @param content JSON content | ||
* @param content JSON content | ||
* @param valueType Resulting type. | ||
* @param <T> Type | ||
* @param <T> Type | ||
* @return instance of type. | ||
*/ | ||
public static <T> T readValue(String content, Class<T> valueType) { | ||
|
@@ -72,8 +76,32 @@ private static ObjectMapper createDefaultMapper() { | |
module.addSerializer(Date.class, new DateSerializer(Date.class)); | ||
module.addDeserializer(Date.class, new DateDeserializer(Date.class)); | ||
var mapper = new ObjectMapper(); | ||
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also have the mixin. |
||
mapper.registerModule(module); | ||
return mapper; | ||
} | ||
|
||
private static ObjectMapper createDefaultWriteMapper() { | ||
var mapper = createDefaultMapper(); | ||
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not needed because it is already in the default mapper. |
||
mapper.setMixInResolver(new WriteMixInResolver()); | ||
return mapper; | ||
} | ||
|
||
@JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
private static class MixIn { | ||
} | ||
|
||
private static class WriteMixInResolver implements ClassIntrospector.MixInResolver { | ||
|
||
@Override | ||
public Class<?> findMixInClassFor(Class<?> cls) { | ||
return MixIn.class; | ||
} | ||
|
||
@Override | ||
public ClassIntrospector.MixInResolver copy() { | ||
return new WriteMixInResolver(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several modules use ObjectMapperTool.getMapper() for writing: https://github.com/search?q=org%3Afolio-org+ObjectMapperTool+getMapper+valueAsString&type=code
I would rather generate the POJOs with
@JsonInclude(JsonInclude.Include.NON_EMPTY)
.Can the RAML tooling been configured to generate this?
If not the POJO generator has a JakartaMigrator that can be renamed to PostProcessor and can add the
@JsonInclude(JsonInclude.Include.NON_EMPTY)
as needed:https://github.com/folio-org/raml-module-builder/blob/v35.3.0/domain-models-maven-plugin/src/main/java/org/folio/rest/tools/GenerateRunner.java#L199
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing JsonInclude.Include.NON_NULL to JsonInclude.Include.NON_EMPTY in POJOs will result in a breaking change for all APIs. The UI might break where it checks not for null but for emptiness. I think it will generate a significant amount of unexpected work for developers.
But with this approach, it will be a choice for each module, to keep old mapper or use new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add documentation to RMB's README and to RMB's upgrading notes how a module can use PostgresClient with the old mapper or the new mapper?