I got a scenario.
Required input and output are JSON.
// Input
{
\"OldObject\": {
\"Time\": 1351
Try JOLT. It is a JSON to JSON transformation library written in Java. It was created on a project that was transforming lot of JSON from an ElasticSearch "backend" to a frontend api.
For the JSON transform you have listed in your problem, the Jolt "shift" spec would be :
// Jolt "shift" spec
{
"OldObject": {
"Time": "NewObject.Time",
"Name": "NewObject.Title", // if the input has "OldObject.Name", copy it's value
// to "NewObject.Title
"quantity": "NewObject.quantity"
}
}
You can do this transformation with JSON patch.
Example with jsonpatch-js:
var transformations = [
{ move: '/OldObject', to: '/NewObject' },
{ remove: '/NewObject/price' },
{ move: '/NewObject/Name', to: '/NewObject/Title' }
];
var oldObject = { "OldObject": { "Time": 1351160457922, "Name": "OName", "quantity": 100, "price": 10 } };
jsonpatch.apply(oldObject, transformations);
I did not test the provided, but should work like that.
There are Java implementations for JSON patch:
Javascript JSON Transformer : https://raw.githubusercontent.com/udhayasoftware/codebase/master/standalone/javascript/TransformJSON.js
We can convert JSON array to JSON object and vice versa. The only thing is we need to be careful in defining the xPaths.
//Transforming JSON array to JSON object:
var inputObj = [{Name:"Senyora"},{Name:"Clinton"}]
sourceXpath = "[].Name";
targetXpath = "Marriage.Couples[].NewName";
// Output = {Marriage:{Couples:[{NewName:"Senyora"},{NewName:"Clinton"}]}}
//Transforming JSON object to JSON array:
var inputObj = {Marriage:{Couples:[{NewName:"Senyora"},{NewName:"Clinton"}]}}
sourceXpath = "Marriage.Couples[].NewName";
targetXpath = "[].Name";
// Output = [{Name:"Senyora"},{Name:"Clinton"}]
/*
Author: Udhayamoorthy
Email: udhayaraagam@gmail.com"
*/
//Code start
function prepareGroup(inputObj, flatted, sourceXpath) {
sourceXpath = sourceXpath.replace(/\[]/g, ".[0-9]*");
var reg = new RegExp(sourceXpath, "g")
var strVal = JSON.stringify(flatted).match(reg);
var groupVal = {};
if (strVal != null)
strVal.forEach(function (data) {
if (flatted[data] != undefined) {
groupVal[data] = flatted[data];
} else {
data = data.replace(/"/g, "");
groupVal[data] = getValue(inputObj, data);
}
})
return groupVal;
}
function processGrouped(obj, targetXpath) {
var flatOutput = {};
var keys = Object.keys(obj);
targetXpath = targetXpath.replace(/\[]./g, "[0-9]");
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var changed = key.match(/(^[0-9]*\.|\W[0-9]*\.)/g);
if (changed) {
changed = JSON.stringify(changed).replace(/\"\./g, "\"");
}
var arrapos = '';
try {
arrapos = JSON.parse(changed);
}
catch (e) {
arrapos = changed;
}
var temp = targetXpath;
if (arrapos != null) {
arrapos.forEach(function (pos) {
pos = "." + pos;
temp = temp.replace("[0-9]", pos)
})
}
//tinkering - started
if (temp.charAt(0) == ".") {
temp = temp.substring(1, temp.length);
}
//tinkering - end
flatOutput[temp] = obj[key];
}
return unflatten(flatOutput);
}
function merge(a, b) {
for (var key in b)
if (b.hasOwnProperty(key)) {
var src = a[key];
var dest = b[key];
if (typeof src === 'object' && typeof dest === 'object') {
merge(src, dest);
} else {
a[key] = b[key];
}
}
return a;
};
function getValue(localObj, xpath) {
//var localObj = JSON.parse(JSON.stringify(obj));
var xpathArr = xpath.split('.');
xpathArr.forEach(function (path) {
localObj = localObj[path];
})
return localObj;
}
function unflatten(target, opts) {
var opts = opts || {}
, delimiter = opts.delimiter || '.'
, result = {}
if (Object.prototype.toString.call(target) !== '[object Object]') {
return target
}
function getkey(key) {
var parsedKey = parseInt(key)
return (isNaN(parsedKey) ? key : parsedKey)
};
Object.keys(target).forEach(function (key) {
var split = key.split(delimiter)
, firstNibble
, secondNibble
, recipient = result
firstNibble = getkey(split.shift())
secondNibble = getkey(split[0])
while (secondNibble !== undefined) {
if (recipient[firstNibble] === undefined) {
recipient[firstNibble] = ((typeof secondNibble === 'number') ? [] : {})
}
recipient = recipient[firstNibble]
if (split.length > 0) {
firstNibble = getkey(split.shift())
secondNibble = getkey(split[0])
}
}
// unflatten again for 'messy objects'
recipient[firstNibble] = unflatten(target[key])
});
//Array Check
var keys = Object.keys(result);
if (keys.length > 0 && keys[0] === "0") {
var output = [];
keys.forEach(function (key) {
output.push(result[key])
});
return output;
}
return result
};
function flatten(target, opts) {
var output = {}
, opts = opts || {}
, delimiter = opts.delimiter || '.'
function getkey(key, prev) {
return prev ? prev + delimiter + key : key
};
function step(object, prev) {
Object.keys(object).forEach(function (key) {
var isarray = opts.safe && Array.isArray(object[key])
, type = Object.prototype.toString.call(object[key])
, isobject = (type === "[object Object]" || type === "[object Array]")
if (!isarray && isobject) {
return step(object[key]
, getkey(key, prev)
)
}
output[getkey(key, prev)] = object[key]
});
if (Object.keys(object) == "") {
if (object instanceof Array) {
output[prev] = [];
} else {
output[prev] = {};
}
}
};
step(target)
return output
};
function isChildAttribute(map, flatted, mapArray) {
var parent = map.sourceXpath;
for (var j = 0; j < mapArray.length; j++) {
var child = mapArray[j].sourceXpath;
if (child.indexOf(parent) != -1 && parent.length < child.length) {
if (child.indexOf(parent + ".") != -1 || child.indexOf(parent + "[]") != -1) {
var temp = child;
temp = temp.replace(/\[]/g, ".0");
if (flatted[temp] != undefined) {
return false;
}
}
}
}
return true;
}
function transformJSON(inputObj, mapArray) {
var flatted = flatten(inputObj);
var finalout = {};
if (mapArray.length > 0 && (mapArray[0].targetXpath).charAt(0) == "[")
finalout = [];
mapArray.forEach(function (map) {
if (isChildAttribute(map, flatted, mapArray)) {
var grouped = prepareGroup(inputObj, flatted, map.sourceXpath);
var output = processGrouped(grouped, map.targetXpath);
finalout = merge(finalout, output); // merge two json objects
}
});
return finalout;
}
//Code end
//How to use (See below) ??
var inputObj = {
a: {
b: [
{
Name: "Tommy",
Location: [
{Place: "Sydney"},
{Place: "Washington"}
],
Info: {age: 23}
},
{
Name: "Sara",
Location: [
{Place: "New York"},
{Place: "New Jercy"}
],
Info: {age: 34}
},
{
Name: "John",
Location: [
{Place: "Chicago"},
{Place: "Detroit"}
],
Info: {age: 78}
}
],
d: {
e: {
f: {
g: {
h: "I Love India"
}
}
}
}
}
};
var mapArray = []; // collect source and target xpath s
var obj = {};
obj.sourceXpath = "a.b[].Name"; // Name is string
obj.targetXpath = "x[].NewName"; // expecting NewName as string
mapArray.push(obj);
//obj = {};
//obj.sourceXpath = "a.b[].Location"; // Location is an array
//obj.targetXpath = "x[].NewName"; // INVALID MAPPING - NewName already mapped
//mapArray.push(obj);
obj = {};
obj.sourceXpath = "a.b[].Location"; // Location is an array
obj.targetXpath = "x[].NewLocation"; // Location data copied to NewLocation array(Place will be present in array elements)
mapArray.push(obj);
obj = {};
obj.sourceXpath = "a.b[].Location[].Place"; // Location is an array
obj.targetXpath = "x[].NewLocation[].NewPlace"; // NewPlace will be created parallel to existing Place.
mapArray.push(obj);
obj = {};
obj.sourceXpath = "a.d.e.f.g.h"; // Transforming attributes at different level
obj.targetXpath = "T.H";
mapArray.push(obj);
var finalout = transformJSON(inputObj, mapArray);
console.log("See line#204 for more about how to use?");
console.log("Transformed JSON = " + JSON.stringify(finalout));
Caution: JSON can't be transformed between different dimensions of array. Count of '[]' in sourceXpath should be equals to count of '[]' in targetXpath and vice versa.
You can try Java library Silencio that allows you to convert each node of the JSON file into new values. You can decide which and how nodes should be transformed.
You can try jmom a little java library
String jsonstring = "...";
JsonValue json = JsonParser.parse(jsonstring);
Jmom jmom = Jmom.instance()
.copy("/OldObject", "/NewObject", true)
.remove("/NewObject/price")
.copy("/NewObject/Name", "/NewObject/Title", true);
jmom.apply(json);
jsonstring = json.toCompactString();
You can use ZORBA and JsonIQ http://www.jsoniq.org/ However, it's a native library, it comes with a wrapper so you can use it in java.