JSONPath使用单个输出转换并映射到不同的数据层

时间:2015-05-13 17:47:39

标签: json xslt xpath transform jsonpath

我正在使用JSONPath和此节点模块https://www.npmjs.com/package/jsonpath-object-transform将JSON obj转换为不同的输出。这类似于XML和XSLT。问题是当我想映射到源数据的不同层并发送到平面输出时。

示例:

var output = {
    storeName: '$.store',
    items: ['$.items',{
        uniqueName: '$.name',
        sku: '$.skus[*].num'
    }]
};

var source = {
    store:'my store',
    items: [{
        name: 'Hammer',
        skus: [{
            num: '12345qwert'
        }]
    }, {
        name: 'Bike',
        skus: [{
            num: 'asdfghhj'
        }, {
            num: 'zxcvbn'
        }]
    }, {
        name: 'Fork',
        skus: [{
            num: '0987dfgh'
        }]
    }]
};

结果是:

{
  "storeName": "my store",
  "items": [
    {
      "uniqueName": "Hammer",
      "sku": "12345qwert"
    },
    {
      "uniqueName": "Bike",
      "sku": "asdfghhj"
    },
    {
      "uniqueName": "Fork",
      "sku": "0987dfgh"
    }
  ]
}

结果的问题是它忽略了Bike obj中的第二个数组项。 items[1].skus[1].num。我相信这样做是因为$.items指示符只知道items数组中的3个obj。

我的预期结果是:

{
      "storeName": "my store",
      "items": [
        {
          "uniqueName": "Hammer",
          "sku": "12345qwert"
        },
        {
          "uniqueName": "Bike",
          "sku": "asdfghhj"
        },
{
          "uniqueName": "Bike",
          "sku": "zxcvbn"
        },
        {
          "uniqueName": "Fork",
          "sku": "0987dfgh"
        }
      ]
    }

如何使用JSONPath实现此输出。

2 个答案:

答案 0 :(得分:1)

这可能是不可能的。你真的在skus而不是项目上进行迭代,所以在理论上表达式应该是这样的:

var output = {
  storeName: '$.store',
  items: ['$.items[*].skus[*]', { // or '$..skus[*]', or perhaps even '$..num'
    uniqueName: '$<<name', // no "parent" operator in JSONPath
    sku: '$.num'
  }]
}

但有两个问题:

1)jsonpath-object-transform似乎没有正确转换子项:省略uniquename,如果省略转换,则生成正确的num条目,但是如果添加转换则为异常被扔了。我认为这是一个错误。

2)即使您可以迭代skus,JSONPath也没有父运算符,因此无法访问当前项.name

无论如何,这是我最好的评估。

答案 1 :(得分:1)

我用我自己的小型库解决了这种问题,它基本上模仿了XSLT处理模型;所以,这里有一个小提琴你的例子:

https://jsfiddle.net/YSharpLanguage/2sa0twny

其中:

var x = document.getElementsByClassName('myContent');
for (var i=0;i<x.length;i++){
  x[i].style.display = 'none';
}

给出:

var source =
{
    store:'my store',
    items: [{
        name: 'Hammer',
        skus: [{
            num: '12345qwert'
        }]
    }, {
        name: 'Bike',
        skus: [{
            num: 'asdfghhj'
        }, {
            num: 'zxcvbn'
        }]
    }, {
        name: 'Fork',
        skus: [{
            num: '0987dfgh'
        }]
    }]
};

function Root(node) {
  return (typeof node.store === "string") &&
         ({ }.toString.call(node.items) === "[object Array]");
}

function SKU(node) {
  return typeof node.num === "string";
}

function FlattenedSKU(node) {
  return SKU(node) && (typeof node.name === "string");
}

var SO_30221930_Transform = { $: [

  [ [ Root ],
    // rewriting rule to process JSONPath's "$"
    // (XSLT-would-be <xsl:template match="/">...)
    function(root) {
      return {

        // (cf. the `String.prototype.of` interpolation helper)
        storeName: "{store}".of(root),

        // (XSLT-would-be <xsl:apply-templates select="items/sku"/>)
        items: root.items.
               // first, get all the SKU nodes (XPath "items//sku")
               nodeset(SKU, true).
               // then, flatten them as [ { name: ..., num: ... } ... ]
               map(function(sku_node) {
                 return {
                   name: "{name}".of(sku_node.parent.parent),
                   num: "{num}".of(sku_node.value),
                 };
               }).
               // finally, rewrite them as [ { uniqueName: ..., num: ... } ... ]
               through(this)
      }
    }
  ],

  [ [ FlattenedSKU ],
    function(sku) {
      return {
        uniqueName: "{name}".of(sku),
        num: "{num}".of(sku)
      };
    }
  ]

] };

var output = source.through(SO_30221930_Transform);
console.log(JSON.stringify(output, null, 2));

以下是其他示例/用例:

JSON transformations, revisited (XSLT look-alike)

(at:https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10

Super-lightweight JSON-to-JSON transformations

(at:https://jsfiddle.net/YSharpLanguage/ppfmmu15/10

&#39;希望这有帮助,