Closed Karric closed 2 years ago
Its possible with custom modifier
package br.com.teste.jolt;
import com.bazaarvoice.jolt.common.Optional;
import com.bazaarvoice.jolt.modifier.function.Function;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class CustomFunctions {
public static final class stringfy extends Function.SingleFunction<Object> {
@Override
protected Optional<Object> applySingle(Object o) {
ObjectMapper objectMapper = new ObjectMapper();
try {
String stringValue = objectMapper.writeValueAsString(o);
return Optional.of(stringValue);
} catch (JsonProcessingException e) {
return Optional.empty();
}
}
}
}
package br.com.teste.jolt;
import com.bazaarvoice.jolt.ContextualTransform;
import com.bazaarvoice.jolt.SpecDriven;
import com.bazaarvoice.jolt.common.Optional;
import com.bazaarvoice.jolt.common.tree.MatchedElement;
import com.bazaarvoice.jolt.common.tree.WalkedPath;
import com.bazaarvoice.jolt.exception.SpecException;
import com.bazaarvoice.jolt.modifier.OpMode;
import com.bazaarvoice.jolt.modifier.TemplatrSpecBuilder;
import com.bazaarvoice.jolt.modifier.function.Function;
import com.bazaarvoice.jolt.modifier.spec.ModifierCompositeSpec;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class CustomModifier implements SpecDriven, ContextualTransform {
private static final Map<String, Function> STOCK_FUNCTIONS = new HashMap<>();
private final ModifierCompositeSpec rootSpec;
static {
STOCK_FUNCTIONS.put("stringfy", new CustomFunctions.stringfy());
}
@SuppressWarnings("unchecked")
private CustomModifier(Object spec, OpMode opMode, Map<String, Function> functionsMap) {
if (spec == null) {
throw new SpecException(opMode.name() + " expected a spec of Map type, got 'null'.");
}
if (!(spec instanceof Map)) {
throw new SpecException(opMode.name() + " expected a spec of Map type, got " + spec.getClass().getSimpleName());
}
if (functionsMap == null || functionsMap.isEmpty()) {
throw new SpecException(opMode.name() + " expected a populated functions' map type, got " + (functionsMap == null ? "null" : "empty"));
}
functionsMap = Collections.unmodifiableMap(functionsMap);
TemplatrSpecBuilder templatrSpecBuilder = new TemplatrSpecBuilder(opMode, functionsMap);
rootSpec = new ModifierCompositeSpec(ROOT_KEY, (Map<String, Object>) spec, opMode, templatrSpecBuilder);
}
@Override
public Object transform(final Object input, final Map<String, Object> context) {
Map<String, Object> contextWrapper = new HashMap<>();
contextWrapper.put(ROOT_KEY, context);
MatchedElement rootLpe = new MatchedElement(ROOT_KEY);
WalkedPath walkedPath = new WalkedPath();
walkedPath.add(input, rootLpe);
rootSpec.apply(ROOT_KEY, Optional.of(input), walkedPath, null, contextWrapper);
return input;
}
/**
* This variant of modifier creates the key/index is missing,
* and overwrites the value if present
*/
public static final class Overwritr extends CustomModifier {
public Overwritr(Object spec) {
this(spec, STOCK_FUNCTIONS);
}
public Overwritr(Object spec, Map<String, Function> functionsMap) {
super(spec, OpMode.OVERWRITR, functionsMap);
}
}
/**
* This variant of modifier only writes when the key/index is missing
*/
public static final class Definr extends CustomModifier {
public Definr(final Object spec) {
this(spec, STOCK_FUNCTIONS);
}
public Definr(Object spec, Map<String, Function> functionsMap) {
super(spec, OpMode.DEFINER, functionsMap);
}
}
/**
* This variant of modifier only writes when the key/index is missing or the value is null
*/
public static class Defaultr extends CustomModifier {
public Defaultr(final Object spec) {
this(spec, STOCK_FUNCTIONS);
}
public Defaultr(Object spec, Map<String, Function> functionsMap) {
super(spec, OpMode.DEFAULTR, functionsMap);
}
}
}
Spec:
[
{
"operation": "shift",
"spec": {
"*": {
"@": "x.&"
}
}
},
{
"operation": "br.com.teste.jolt.CustomModifier$Overwritr",
"spec": {
"*": "=stringfy(@(0))"
}
},
{
"operation": "shift",
"spec": {
"x": ""
}
}
]
output "{\"random\":69,\"random float\":41.842,\"bool\":false,\"date\":\"1988-01-23\",\"array\":[\"Pearline\",\"Marita\",\"Sonni\"],\"array of objects\":[{\"index\":0,\"index start at 5\":5}],\"Ernesta\":{\"age\":73}}"
I have a situation where my only method for modifying an API response's data is JOLT. For various reasons I need to 'stringify' the response using JOLT.
It's easy enough to use =concat to do this but it doesn't produce a valid JSON format, or something that's easily reversed.
Example Input
JOLT
OUTPUT
DESIRED OUTPUT
I tried to check the JOLT java code to see if I could tweak concat's behaviour to not lose the quotation marks, but I could not find anything.
I thought about using concat to restore the double quotes and colon but I quickly gave up. If anyone has a better technique, please let me know. Ideally the JOLT is generalized and not input-specific.