Skip to content
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

fix: remove jsonb_array and fix jsonb data types such that it can be used in schema design and graphql api #4409

Merged
merged 35 commits into from
Nov 27, 2024
Merged
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4cd9812
fix: remove jsonb_array type
mswertz Oct 29, 2024
5ba651b
fix: remove jsonb_array type
mswertz Oct 29, 2024
adfd5d1
fix tests
mswertz Oct 29, 2024
fe90ef7
Merge branch 'master' into fix/remove_json_array
mswertz Nov 4, 2024
3238649
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 6, 2024
69aa6bd
wip
mswertz Nov 6, 2024
917fdb6
undo|
mswertz Nov 6, 2024
8889644
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 6, 2024
02141e3
add jsonb to graphql api
mswertz Nov 6, 2024
41443eb
many fixes for the proper json passing
mswertz Nov 6, 2024
16dcee1
fix test
mswertz Nov 6, 2024
e5bedd1
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 7, 2024
8e20cad
add test
mswertz Nov 7, 2024
ea0c91a
Merge branch 'master' into fix/remove_json_array
mswertz Nov 11, 2024
3c1aa07
merged
mswertz Nov 15, 2024
092c9d2
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 18, 2024
d5dd710
expand test coverage
mswertz Nov 18, 2024
59b7b78
Merge branch 'master' into fix/remove_json_array
mswertz Nov 18, 2024
fc50cf2
remove unused code
mswertz Nov 18, 2024
8f34bdb
merge
mswertz Nov 19, 2024
5febc75
Merge branch 'master' into fix/remove_json_array
svandenhoek Nov 25, 2024
da8e178
Updated code from #4323 to be compatible with this branch
svandenhoek Nov 25, 2024
3755cbd
updated docs
svandenhoek Nov 25, 2024
2188e18
generalized GraphqlCustomTypes in switch
svandenhoek Nov 25, 2024
8414b94
serialize should only throw a CoercingSerializeException (https://www…
svandenhoek Nov 25, 2024
c7ddff2
Updated toJsonb to include full validation
svandenhoek Nov 25, 2024
dad3e7f
Improved JSON validation (no trailing data, duplicate check)
svandenhoek Nov 25, 2024
e3d1243
auto-formatting
svandenhoek Nov 25, 2024
996dfe1
WIP: front-end validation
svandenhoek Nov 26, 2024
d0833c6
Added tests
svandenhoek Nov 26, 2024
150161c
fixes null giving wrong front-end error message
svandenhoek Nov 26, 2024
70f505f
fixed comments
svandenhoek Nov 26, 2024
d2e2d76
more comment fixes
svandenhoek Nov 26, 2024
ff6cdbf
processed feedback
svandenhoek Nov 26, 2024
83f7eec
formatting
svandenhoek Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Improved JSON validation (no trailing data, duplicate check)
svandenhoek committed Nov 25, 2024
commit dad3e7fa69b8ec6a9e03534f0da94c51cd39e0b1
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package org.molgenis.emx2.graphql;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.schema.*;
import jakarta.servlet.http.Part;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import org.molgenis.emx2.BinaryFileWrapper;
import org.molgenis.emx2.utils.MolgenisObjectMapper;

public class GraphqlCustomTypes {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final MolgenisObjectMapper objectMapper = MolgenisObjectMapper.INTERNAL;

private GraphqlCustomTypes() {
// hide constructor
@@ -28,7 +28,7 @@ private GraphqlCustomTypes() {
public String serialize(Object dataFetcherResult) {
// Convert Java object to JSON string
try {
return objectMapper.writeValueAsString(dataFetcherResult);
return objectMapper.getWriter().writeValueAsString(dataFetcherResult);
} catch (JsonProcessingException e) {
throw new CoercingSerializeException(
"Unable to serialize to JSON string: " + e.getMessage());
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.molgenis.emx2.utils;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.molgenis.emx2.MolgenisException;

public enum MolgenisObjectMapper {
INTERNAL {
@Override
void configureSpecific(ObjectMapper objectMapper) {
// Enable source inclusion in error location
objectMapper.configure(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature(), true);
}
},
PUBLIC;

// Immutable singletons
private ObjectReader reader;
private ObjectWriter writer;

public ObjectReader getReader() {
return reader;
}

public ObjectWriter getWriter() {
return writer;
}

MolgenisObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
configureGeneric(objectMapper);
configureSpecific(objectMapper);

this.reader = objectMapper.reader();
this.writer = objectMapper.writer();
}

private void configureGeneric(ObjectMapper objectMapper) {
// No trailing data allowed
objectMapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
// Duplicate check reduces performance
objectMapper.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
}

/**
* Override for specific configs.
*/
void configureSpecific(ObjectMapper objectMapper) {}

/**
* @see #validate(JsonNode)
*/
public String validate(String json) throws JsonProcessingException {
return validate(reader.readTree(json)).toString();
}

/**
* Validate JSON if it adheres to Molgenis EMX2 specific requirements.
*/
public JsonNode validate(JsonNode rootNode) {
if (!(rootNode.isObject() || rootNode.isArray())) {
throw new MolgenisException(
"Only an object or array is allowed as root element. Found type is: "
+ rootNode.getNodeType().name());
}
return rootNode;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package org.molgenis.emx2.utils;

import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.sql.Timestamp;
@@ -22,13 +19,7 @@
import org.molgenis.emx2.*;

public class TypeUtils {
private static final ObjectMapper objectMapper = new ObjectMapper();

static {
// Enable source inclusion in error location
objectMapper.configure(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature(), true);
objectMapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
}
private static final MolgenisObjectMapper objectMapper = MolgenisObjectMapper.INTERNAL;

private static final String LOOSE_PARSER_FORMAT =
"[yyyy-MM-dd]['T'[HHmmss][HHmm][HH:mm:ss][HH:mm][.SSSSSSSSS][.SSSSSSSS][.SSSSSSS][.SSSSSS][.SSSSS][.SSSS][.SSS][.SS][.S]][OOOO][O][z][XXXXX][XXXX]['['VV']']";
@@ -267,7 +258,7 @@ public static JSONB toJsonb(Object v) {
String value = toString(v);
if (value != null) {
try {
v = objectMapper.readTree(value);
v = objectMapper.getReader().readTree(value);
} catch (Exception e) {
throw new MolgenisException("Invalid json", e);
}
@@ -276,22 +267,13 @@ public static JSONB toJsonb(Object v) {
}
}
if (v instanceof JsonNode) {
return org.jooq.JSONB.valueOf(validateJson((JsonNode) v).toString());
return org.jooq.JSONB.valueOf(objectMapper.validate((JsonNode) v).toString());
}

// Other input is invalid (no casting due to ensuring validateJson() is executed).
throw new ClassCastException("Cannot cast '" + v.toString() + "' to JSONB");
}

public static JsonNode validateJson(JsonNode rootNode) throws MolgenisException {
if (!(rootNode.isObject() || rootNode.isArray())) {
throw new MolgenisException(
"Only an object or array is allowed as root element. Found type is: "
+ rootNode.getNodeType().name());
}
return rootNode;
}

public static String toText(Object v) {
if (v == null) return null;
if (v instanceof String) {