【问题标题】:JSON to JSON transformerJSON 到 JSON 转换器
【发布时间】:2012-10-15 14:49:30
【问题描述】:

我有一个场景。

所需的输入和输出是 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 可能会导致开销。

【问题讨论】:

标签: java json xslt jackson


【解决方案1】:

试试JOLT。它是一个用 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"
    }
}

【讨论】:

    【解决方案2】:

    您可以使用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 implementations

    【讨论】:

    • 有点担心 - 这在性能方面是否足够好,因为这个 Javascript 必须每秒修补大约 1000 个 JSON 对象?
    • 这取决于你的情况。如果您想在服务器端执行此操作,您可以使用不同的语言进行不同的实现。我发布此内容是因为您的问题中有一个 javascript 标签。
    • 我正在使用 java,它将是基于 windows 的桌面应用程序。
    【解决方案3】:

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

    【讨论】:

    【解决方案4】:

    你可以试试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();
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        {
          steps: [
            {
              rename {
                 config {
                    from: "OldObject"
                    to: "NewObject"
                 }
              }
            }
        
            {
              removeField {
                config {
                  path: "NewObject.price"
                }
              }
            }
        
            {
              rename {
                config {
                  from: "NewObject.Name"
                  to: "NewObject.Title"
                }
              }
            }
          ]
        }
        

        【讨论】:

          【解决方案7】:

          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 中“[]”的计数,反之亦然。

          【讨论】:

            猜你喜欢
            • 2010-12-04
            • 1970-01-01
            • 2011-09-12
            • 1970-01-01
            • 1970-01-01
            • 2018-01-15
            • 2018-01-19
            • 2021-09-12
            • 1970-01-01
            相关资源
            最近更新 更多