我正在使用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实现此输出。
答案 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;希望这有帮助,