2015-05-13 3 views
0

Я использую JSONPath, и этот модуль узла https://www.npmjs.com/package/jsonpath-object-transform преобразует объект JSON в другой выход. Это похоже на XML и XSLT. Проблема в том, когда я хочу сопоставить разные уровни исходных данных и отправить на плоский вывод.JSONPath преобразовывать и отображать разные уровни данных с одним выходом

Примеры:

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 обозначение знает только 3 объекта в массиве элементов.

Мой ожидаемый результат был:

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

Как я могу добиться этого результата с помощью JSONPath.

+0

возможно дубликат [JsonPath/Джексон: как десериализации JSON массив один Объект ("\ [1,2,3 \]" -> экземпляр Vector3d)?] (Http://stackoverflow.com/questions/29471589/jsonpath-jackson-how-to-deserialize-json-array-to-a -Single объектно-1-2-3) –

ответ

1

Это может быть невозможно. Вы действительно итерация артикулов, а не предметов, так что в теории выражение должно быть что-то вроде этого:

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

Но есть две проблемы:

1) jsonpath-объект-преобразование оказывается не правильно преобразовать дети: оставляя uniquename, если вы опустите преобразование, создаются правильные записи num, но если вы добавите преобразование, будет выбрано исключение. Я предполагаю, что это ошибка.

2) даже если вы могли бы перебирать skus, у JSONPath нет родительского оператора, поэтому не было бы способа получить доступ к текущему элементу .name.

В любом случае, это моя лучшая оценка.

1

Я решил эту проблему с моей собственной небольшой библиотекой, которая по существу имитирует XSLT-модель обработки; так, вот скрипку для примера:

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

где:

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

дает:

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

Вот другие примеры/случаи использования:

JSON transformations, revisited (XSLT look-alike)

(по адресу: https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10)

Super-lightweight JSON-to-JSON transformations

(по адресу: https://jsfiddle.net/YSharpLanguage/ppfmmu15/10)

«Надеюсь, что это помогает,

 Смежные вопросы

  • Нет связанных вопросов^_^