Skip to content

Commit c2db13c

Browse files
committed
java-0.9.0 - align initialization method, multiple fixes and add json-smart
1 parent 575603b commit c2db13c

File tree

61 files changed

+1796
-1151
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1796
-1151
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
}
2424
```
2525

26+
- See available adapters [here](https://github.com/nlighten-oss/json-transform/tree/main/java/json-transform/src/main/java/co/nlighten/jsontransform/adapters)
27+
2628
Then in the code where you want to transform JSON objects:
2729

2830
```java
@@ -32,4 +34,14 @@ Then in the code where you want to transform JSON objects:
3234
// 'input' - The input of the transformer (referred as '$')
3335
// 'additionalContext' - (optional) Map of additional inputs to refer during transformation
3436
Object transformed = transformer.transform(input, additionalContext);
37+
```
38+
39+
### JavaScript
40+
41+
```js
42+
// 'definition' is the spec of the transformer
43+
const transformer = new JsonTransformer(definition);
44+
// 'input' - The input of the transformer (referred as '$')
45+
// 'additionalContext' - (optional) Map of additional inputs to refer during transformation
46+
const result = await transformer.transform(input, additionalContext);
3547
```

java/json-transform/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ plugins {
99
}
1010

1111
group 'co.nlighten'
12-
version = '0.8.0'
12+
version = '0.9.0'
1313

1414
ext {
1515
gsonVersion = "2.10.1"
1616
jsonVersion = '20240303'
1717
jsonPathVersion = "2.9.0"
1818
jmhVersion = "1.36"
1919
jacksonBindVersion = "2.17.1"
20+
jsonSmartVersion = "2.5.2"
2021
snakeYamlVersion = "2.7"
2122
coNlightenShortUuidVersion = "0.1.1"
2223
slf4jVersion = "2.0.11"
@@ -39,6 +40,7 @@ dependencies {
3940
/** JSON **/
4041
compileOnly "com.google.code.gson:gson:${gsonVersion}"
4142
compileOnly "com.fasterxml.jackson.core:jackson-databind:${jacksonBindVersion}"
43+
compileOnly "net.minidev:json-smart:${jsonSmartVersion}"
4244
implementation "org.json:json:${jsonVersion}" // for XML conversion
4345
implementation "com.jayway.jsonpath:json-path:${jsonPathVersion}"
4446

@@ -52,6 +54,7 @@ dependencies {
5254
testImplementation 'org.junit.jupiter:junit-jupiter'
5355
testImplementation "com.google.code.gson:gson:${gsonVersion}"
5456
testImplementation "com.fasterxml.jackson.core:jackson-databind:${jacksonBindVersion}"
57+
testImplementation "net.minidev:json-smart:${jsonSmartVersion}"
5558
}
5659

5760
jar { archiveClassifier = '' }

java/json-transform/src/main/java/co/nlighten/jsontransform/DebuggableTransformerFunctions.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ public class DebuggableTransformerFunctions extends TransformerFunctions{
1010

1111
public record TransformerDebugInfo(Object result) {}
1212

13-
public DebuggableTransformerFunctions(JsonAdapter<?, ?, ?> adapter) {
14-
super(adapter);
13+
public DebuggableTransformerFunctions() {
1514
debugResults = new HashMap<>();
1615
}
1716

@@ -30,12 +29,12 @@ private TransformerFunctions.FunctionMatchResult<Object> auditAndReturn(String p
3029
return matchResult;
3130
}
3231

33-
public TransformerFunctions.FunctionMatchResult<Object> matchObject(String path, Object definition, ParameterResolver resolver, JsonTransformerFunction transformer) {
34-
return auditAndReturn(path, super.matchObject(path, definition, resolver, transformer));
32+
public TransformerFunctions.FunctionMatchResult<Object> matchObject(JsonAdapter<?,?,?> adapter, String path, Object definition, ParameterResolver resolver, JsonTransformerFunction transformer) {
33+
return auditAndReturn(path, super.matchObject(adapter, path, definition, resolver, transformer));
3534
}
3635

37-
public TransformerFunctions.FunctionMatchResult<Object> matchInline(String path, String value, ParameterResolver resolver, JsonTransformerFunction transformer) {
38-
return auditAndReturn(path, super.matchInline(path, value, resolver, transformer));
36+
public TransformerFunctions.FunctionMatchResult<Object> matchInline(JsonAdapter<?,?,?> adapter, String path, String value, ParameterResolver resolver, JsonTransformerFunction transformer) {
37+
return auditAndReturn(path, super.matchInline(adapter, path, value, resolver, transformer));
3938
}
4039

4140
public Map<String, TransformerDebugInfo> getDebugResults() {

java/json-transform/src/main/java/co/nlighten/jsontransform/JsonTransformer.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class JsonTransformer implements Transformer {
1616
private final JsonAdapter<?, ?, ?> adapter;
1717
protected final Object definition;
1818

19+
private static final TransformerFunctionsAdapter DEFAULT_TRANSFORMER_FUNCTIONS = new TransformerFunctions();
1920
private final JsonTransformerFunction JSON_TRANSFORMER;
2021
private final TransformerFunctionsAdapter transformerFunctions;
2122

@@ -24,7 +25,7 @@ public JsonTransformer(
2425
final JsonAdapter<?, ?, ?> adapter,
2526
final TransformerFunctionsAdapter functionsAdapter) {
2627
this.adapter = adapter != null ? adapter : JsonTransformerConfiguration.get().getAdapter();
27-
this.transformerFunctions = functionsAdapter != null ? functionsAdapter : JsonTransformerConfiguration.get().getFunctionsAdapter();
28+
this.transformerFunctions = functionsAdapter != null ? functionsAdapter : DEFAULT_TRANSFORMER_FUNCTIONS;
2829
this.definition = this.adapter.wrap(definition);
2930
this.JSON_TRANSFORMER = this::fromJsonElement;
3031
}
@@ -42,9 +43,13 @@ public JsonTransformer(
4243
}
4344

4445
public JsonTransformer(final Object definition) {
45-
this(definition, JsonTransformerConfiguration.get().getFunctionsAdapter());
46+
this(definition, DEFAULT_TRANSFORMER_FUNCTIONS);
4647
}
4748

49+
public Object transform(Object payload, Map<String, Object> additionalContext, boolean allowReturningStreams, boolean unwrap) {
50+
var result = transform(payload, additionalContext, allowReturningStreams);
51+
return unwrap ? adapter.unwrap(result) : result;
52+
}
4853

4954
public Object transform(Object payload, Map<String, Object> additionalContext, boolean allowReturningStreams) {
5055
if (definition == null) {
@@ -60,7 +65,7 @@ protected Object fromJsonPrimitive(String path, Object definition, co.nlighten.j
6065
try {
6166
var val = adapter.getAsString(definition);
6267
// test for inline function (e.g. $$function:...)
63-
var match = transformerFunctions.matchInline(path, val, resolver, JSON_TRANSFORMER);
68+
var match = transformerFunctions.matchInline(adapter, path, val, resolver, JSON_TRANSFORMER);
6469
if (match != null) {
6570
var matchResult = match.result();
6671
if (matchResult instanceof JsonElementStreamer streamer) {
@@ -79,7 +84,7 @@ protected Object fromJsonPrimitive(String path, Object definition, co.nlighten.j
7984

8085

8186
protected Object fromJsonObject(String path, Object definition, co.nlighten.jsontransform.ParameterResolver resolver, boolean allowReturningStreams) {
82-
var match = transformerFunctions.matchObject(path, definition, resolver, JSON_TRANSFORMER);
87+
var match = transformerFunctions.matchObject(adapter, path, definition, resolver, JSON_TRANSFORMER);
8388
if (match != null) {
8489
var res = match.result();
8590
return res instanceof JsonElementStreamer s

java/json-transform/src/main/java/co/nlighten/jsontransform/JsonTransformerConfiguration.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,4 @@ public JsonTransformerConfiguration(JsonAdapter<?, ?, ?> adapter) {
3535
public JsonAdapter<?, ?, ?> getAdapter() {
3636
return this.adapter;
3737
}
38-
39-
public DebuggableTransformerFunctions getDebuggableAdapter() {
40-
return new DebuggableTransformerFunctions(this.adapter);
41-
}
42-
43-
public TransformerFunctionsAdapter getFunctionsAdapter() {
44-
return new TransformerFunctions(this.adapter);
45-
}
4638
}

java/json-transform/src/main/java/co/nlighten/jsontransform/TransformerFunctions.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ public class TransformerFunctions implements TransformerFunctionsAdapter {
2424
public static final String ESCAPE_DOLLAR = "\\$";
2525
public static final String ESCAPE_HASH = "\\#";
2626

27-
2827
private static Map<String, TransformerFunction> functions = Map.of();
29-
private final JsonAdapter<?, ?, ?> jsonAdapter;
3028

3129
static {
3230
registerFunctions(
@@ -113,10 +111,6 @@ public class TransformerFunctions implements TransformerFunctionsAdapter {
113111
);
114112
}
115113

116-
public TransformerFunctions(JsonAdapter<?, ?, ?> adapter) {
117-
this.jsonAdapter = adapter;
118-
}
119-
120114
@SafeVarargs
121115
public synchronized static void registerFunctions(Map.Entry<String, TransformerFunction>... moreFunctions) {
122116
var additions = Arrays.stream(moreFunctions).filter(x -> {
@@ -138,19 +132,19 @@ public synchronized static void registerFunctions(Map.Entry<String, TransformerF
138132
/**
139133
* Checks the context for a registered object function and returns the result if matched
140134
*/
141-
public FunctionMatchResult<Object> matchObject(String path, Object definition, co.nlighten.jsontransform.ParameterResolver resolver, JsonTransformerFunction transformer) {
135+
public FunctionMatchResult<Object> matchObject(JsonAdapter<?,?,?> adapter, String path, Object definition, co.nlighten.jsontransform.ParameterResolver resolver, JsonTransformerFunction transformer) {
142136
if (definition == null) {
143137
return null;
144138
}
145139
// look for an object function
146140
// (precedence is all internal functions sorted alphabetically first, then client added ones second, by registration order)
147141
for (String key : functions.keySet()) {
148-
if (jsonAdapter.has(definition, FUNCTION_KEY_PREFIX + key)) {
142+
if (adapter.has(definition, FUNCTION_KEY_PREFIX + key)) {
149143
var func = functions.get(key);
150144
var context = new ObjectFunctionContext(
151145
path,
152146
definition,
153-
jsonAdapter,
147+
adapter,
154148
FUNCTION_KEY_PREFIX + key,
155149
func, resolver, transformer);
156150
var resolvedPath = path + "." + FUNCTION_KEY_PREFIX + key;
@@ -166,7 +160,7 @@ public FunctionMatchResult<Object> matchObject(String path, Object definition, c
166160
return null;
167161
}
168162

169-
private InlineFunctionContext tryParseInlineFunction(String path, String value, co.nlighten.jsontransform.ParameterResolver resolver,
163+
private InlineFunctionContext tryParseInlineFunction(JsonAdapter<?,?,?> adapter, String path, String value, co.nlighten.jsontransform.ParameterResolver resolver,
170164
JsonTransformerFunction transformer) {
171165
var matcher = inlineFunctionRegex.matcher(value);
172166
if (matcher.find()) {
@@ -182,7 +176,7 @@ private InlineFunctionContext tryParseInlineFunction(String path, String value,
182176
var arg = argMatcher.group(1);
183177
var trimmed = argMatcher.group(1).trim();
184178
if (trimmed.startsWith(QUOTE_APOS) && trimmed.endsWith(QUOTE_APOS) && trimmed.length() > 1) {
185-
arg = jsonAdapter.getAsString(jsonAdapter.parse(trimmed));
179+
arg = adapter.getAsString(adapter.parse(trimmed));
186180
//otherwise, take the whole argument as-is
187181
}
188182
args.add(arg);
@@ -198,7 +192,7 @@ private InlineFunctionContext tryParseInlineFunction(String path, String value,
198192
return new InlineFunctionContext(
199193
path + "/" + FUNCTION_KEY_PREFIX + functionKey,
200194
input, args,
201-
jsonAdapter,
195+
adapter,
202196
functionKey,
203197
function,
204198
resolver, transformer);
@@ -207,9 +201,9 @@ private InlineFunctionContext tryParseInlineFunction(String path, String value,
207201
return null;
208202
}
209203

210-
public FunctionMatchResult<Object> matchInline(String path, String value, ParameterResolver resolver, JsonTransformerFunction transformer) {
204+
public FunctionMatchResult<Object> matchInline(JsonAdapter<?,?,?> adapter, String path, String value, ParameterResolver resolver, JsonTransformerFunction transformer) {
211205
if (value == null) return null;
212-
var context = tryParseInlineFunction(path, value, resolver, transformer);
206+
var context = tryParseInlineFunction(adapter, path, value, resolver, transformer);
213207
if (context == null) {
214208
return null;
215209
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package co.nlighten.jsontransform;
22

3+
import co.nlighten.jsontransform.adapters.JsonAdapter;
4+
35
public interface TransformerFunctionsAdapter {
4-
TransformerFunctions.FunctionMatchResult<Object> matchInline(String path, String value, ParameterResolver resolver, JsonTransformerFunction transformer);
6+
TransformerFunctions.FunctionMatchResult<Object> matchInline(JsonAdapter<?,?,?> adapter, String path, String value, ParameterResolver resolver, JsonTransformerFunction transformer);
57

6-
TransformerFunctions.FunctionMatchResult<Object> matchObject(String path, Object definition, ParameterResolver resolver, JsonTransformerFunction transformer);
8+
TransformerFunctions.FunctionMatchResult<Object> matchObject(JsonAdapter<?,?,?> adapter, String path, Object definition, ParameterResolver resolver, JsonTransformerFunction transformer);
79
}

java/json-transform/src/main/java/co/nlighten/jsontransform/adapters/JsonAdapter.java

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import co.nlighten.jsontransform.ParameterResolver;
44
import com.google.gson.JsonPrimitive;
5-
import com.jayway.jsonpath.DocumentContext;
6-
import com.jayway.jsonpath.JsonPath;
5+
import com.jayway.jsonpath.*;
76

87
import java.lang.reflect.Array;
98
import java.math.BigDecimal;
@@ -31,15 +30,19 @@ public abstract class JsonAdapter<JE, JA extends Iterable<JE>, JO extends JE> {
3130
private final JsonObjectAdapter<JE, JA, JO> jObject;
3231
private final JsonArrayAdapter<JE, JA, JO> jArray;
3332

33+
protected final ParseContext jsonPath;
34+
protected final com.jayway.jsonpath.Configuration jsonPathConfiguration;
35+
3436
public JsonAdapter(
3537
Supplier<JsonObjectAdapter<JE, JA, JO>> objectAdapterSupplier,
36-
Supplier<JsonArrayAdapter<JE, JA, JO>> arrayAdapterSupplier) {
38+
Supplier<JsonArrayAdapter<JE, JA, JO>> arrayAdapterSupplier,
39+
com.jayway.jsonpath.Configuration jsonPathConfiguration) {
3740
this.jObject = objectAdapterSupplier.get();
3841
this.jArray = arrayAdapterSupplier.get();
42+
this.jsonPathConfiguration = jsonPathConfiguration;
43+
this.jsonPath = JsonPath.using(jsonPathConfiguration);
3944
}
4045

41-
public abstract String getName();
42-
4346
/**
4447
* Checks if the given object is a Json element
4548
* @param value the object to check
@@ -399,23 +402,56 @@ public boolean isEmpty(Object value) {
399402
return false;
400403
}
401404

402-
/**
403-
* Setup JsonPath using specific provider for it
404-
*/
405-
public abstract void setupJsonPath();
406-
407405
/**
408406
* Returns a document context for the given payload (Using JsonPath)
409407
* @param payload the payload to create a document context for
410408
* @return a document context
411409
*/
412-
public DocumentContext getDocumentContext(Object payload) {
413-
setupJsonPath();
410+
public DocumentContext getDocumentContext(Object payload, Iterable<String> options) {
414411
Object document = payload;
415412
if (!is(payload)) {
416413
document = wrap(payload);
417414
}
418-
return JsonPath.parse(document);
415+
var parseContext = jsonPath;
416+
if (options != null) {
417+
var opts = new HashSet<Option>();
418+
for (var option : options) {
419+
opts.add(Option.valueOf(option));
420+
}
421+
parseContext = JsonPath.using(new Configuration.ConfigurationBuilder()
422+
.jsonProvider(jsonPathConfiguration.jsonProvider())
423+
.mappingProvider(jsonPathConfiguration.mappingProvider())
424+
.options(opts)
425+
.build());
426+
}
427+
return parseContext.parse(document);
428+
}
429+
430+
public DocumentContext getDocumentContext(Object payload) {
431+
return getDocumentContext(payload, null);
432+
}
433+
434+
public boolean nodesComparable() {
435+
return true;
436+
}
437+
438+
/**
439+
* Checks if the given objects are equal based on Json implementation
440+
* @param value the first object
441+
* @param other the second object
442+
* @return true if the objects are equal
443+
*/
444+
public boolean areEqual(Object value, Object other) {
445+
return Objects.equals(value, other);
446+
}
447+
448+
/**
449+
* Returns the hash code of the given object
450+
* @param value the object to get the hash code for
451+
* @return the hash code of the object
452+
*/
453+
public int hashCode(Object value) {
454+
return value == null ? 0 : value.hashCode();
419455
}
420456

421457
/**
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package co.nlighten.jsontransform.adapters;
2+
3+
public class JsonAdapterHelpers {
4+
private static final String BACKSLASH = "\\";
5+
public static String singleQuotedStringToDoubleQuoted(String value) {
6+
return "\"" +
7+
value.substring(1, value.length() - 1)
8+
.replace("\"", BACKSLASH + "\"")
9+
.replace(BACKSLASH + "'", "'") +
10+
"\"";
11+
}
12+
}

0 commit comments

Comments
 (0)