33

我有一个场景。

所需的输入和输出是 JSON。

// Input
{
  "OldObject": {
    "Time": 1351160457922,
    "Name": "OName",
    "quantity": 100,
    "price": 10
  }
}


// Output
{
  "NewObject": {
    "Time": 1351160457922,
    "Title": "OName",
    "quantity": 100
  }
}

我需要一些转换代码或者最好是 xslt 类型的语言来将 json 从一种格式转换为另一种格式。该转换器还需要快速,因为转换将在运行中完成。

编辑
我没有收到 INPUT 对象的定义,它可能会在运行时更改。但如果需要,我可以将类用于 OUTPUT 对象。我曾尝试以json -> xml -> xslt -> xml -> json的方式执行此操作,但此时每秒接收大约 1000 个对象,此过程可能会产生开销。
我也不能使用 JavaScript,因为 myApp 是简单的基于 Windows 的 Java 应用程序,使用 JavaScript 可能会导致开销。

4

7 回答 7

34

试试颠簸。它是一个用 Java 编写的 JSON 到 JSON 转换库。它是在将大量 JSON 从 ElasticSearch“后端”转换为前端 api 的项目中创建的。

对于您在问题中列出的 JSON 转换,Jolt “shift”规范将是:

// 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"
    }
}
于 2013-07-01T20:34:15.407 回答
14

您可以使用JSON patch进行此转换。

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);

我没有测试提供的,但应该像那样工作。

JSON补丁有Java实现

于 2012-10-25T12:20:28.690 回答
6

您可以使用 ZORBA 和 JsonIQ http://www.jsoniq.org/ 但是,它是一个本地库,它带有一个包装器,因此您可以在 java 中使用它。

于 2012-11-06T20:43:34.797 回答
2

你可以试试jmom一个小的 java 库

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();
于 2019-11-20T18:21:34.843 回答
1

Javascript JSON 转换器: https ://raw.githubusercontent.com/udhayasoftware/codebase/master/standalone/javascript/TransformJSON.js

我们可以将 JSON 数组转换为 JSON 对象,反之亦然。唯一的事情是我们在定义 xPath 时需要小心。

//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));

注意:JSON 不能在数组的不同维度之间转换。sourceXpath 中“[]”的计数应等于 targetXpath 中“[]”的计数,反之亦然。

于 2015-01-05T13:01:49.177 回答
1

您可以尝试 Java 库Silencio,它允许您将 JSON 文件的每个节点转换为新值。您可以决定应该转换哪些节点以及如何转换。

于 2015-10-18T18:26:40.763 回答
1

另一种选择是使用 Logz.io Sawmill库。您定义一个管道并执行它。以你为例:

{
  steps: [
    {
      rename {
         config {
            from: "OldObject"
            to: "NewObject"
         }
      }
    }

    {
      removeField {
        config {
          path: "NewObject.price"
        }
      }
    }

    {
      rename {
        config {
          from: "NewObject.Name"
          to: "NewObject.Title"
        }
      }
    }
  ]
}
于 2018-02-22T13:58:39.540 回答