JSON Получить родительский объект из дочернего объекта

Как я могу получить скидку, если brand_id == '983'.

Пример JSON:

{
     "prods": [
               {
            "info": {
                  "rate": 100
                    },
            "grocery": [
                     {
                      "brand": "A",
                      "brand_id": "983"
                     },
                     {
                      "brand": "B",
                      "brand_id": "253"
                     }
                     ],
             "discount": "20"
         }
     ]
}

Я пробовал до сих пор

$.prods[*].grocery[?(@.brand_id=='983')]

Это возвращает мне список/массив совпадающих объектов. Но я не могу вернуться в дерево. Любая помощь по этому поводу?

Ответ 1

Действительно, JSONPath не очень хорош в этом, поэтому я решил эту проблему с моей собственной небольшой библиотекой; так, вот скрипка для вашего примера:

https://jsfiddle.net/YSharpLanguage/j9oetwnn/3

где:

var products = {
     "prods": [
        {
            "info": {
                  "rate": 85
                    },
            "grocery": [
                     {
                      "brand": "C",
                      "brand_id": "984"
                     },
                     {
                      "brand": "D",
                      "brand_id": "254"
                     }
                     ],
             "discount": "15"
        },
        {
            "info": {
                  "rate": 100
                    },
            "grocery": [
                     {
                      "brand": "A",
                      "brand_id": "983"
                     },
                     {
                      "brand": "B",
                      "brand_id": "253"
                     }
                     ],
             "discount": "20"
         }
     ]
};

function GroceryItem(obj) {
  return (typeof obj.brand === "string") && (typeof obj.brand_id === "string");
}

    // last parameter set to "true", to grab all the "GroceryItem" instances
    // at any depth:
var itemsAndDiscounts = [ products ].nodeset(GroceryItem, true).
    map(
      function(node) {
        var item = node.value, // node.value: the current "GroceryItem" (aka "$.prods[*].grocery[*]")

            discount = node.parent. // node.parent: the array of "GroceryItem" (aka "$.prods[*].grocery")
                       parent. // node.parent.parent: the product (aka "$.prods[*]")
                       discount; // node.parent.parent.discount: the product discount

        // finally, project into an easy-to-filter form:
        return { id: item.brand_id, discount: discount };
      }
    ),
    discountOfItem983;

discountOfItem983 = itemsAndDiscounts.
  filter
  (
    function(mapped) {
      return mapped.id === "983";
    }
  )
  [0].discount;

console.log("All items and discounts: " + JSON.stringify(itemsAndDiscounts, null, 2));

console.log("Discount of #983: " + discountOfItem983);

дает:

All items and discounts: [
  {
    "id": "984",
    "discount": "15"
  },
  {
    "id": "254",
    "discount": "15"
  },
  {
    "id": "983",
    "discount": "20"
  },
  {
    "id": "253",
    "discount": "20"
  }
]
Discount of #983: 20

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

JSON к какой-то-разметке

Преобразования JSON, пересмотренные (похожий XSLT)

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

JSON-в-JSON

Супер-легкие преобразования JSON-JSON

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

эквивалент JavaScript...

Раздел XSLT 3.0 REC 14.4 Пример: группирование узлов на основе общих значений

(at: http://jsfiddle.net/YSharpLanguage/8bqcd0ey/1)

Cf. https://www.w3.org/TR/xslt-30/#grouping-examples

эквивалент JavaScript...

Случаи использования JSONiq Раздел 1.1.2. Группировка запросов для JSON

(at: https://jsfiddle.net/YSharpLanguage/hvo24hmk/3)

Cf. http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping

'Надеюсь, что это поможет,

Ответ 2

Вы можете написать функцию, которая возвращает родительский node. После этого вы должны разработать функцию, которая перемещает (перемещает) весь объект и все его узлы и массивы, и когда он найдет желаемый идентификатор, ну, вы просто получите родителя и получите скидку.

Здесь у вас есть самый простой пример функции, возвращающей родительский node:

const myVar = {
  "prods": [{
    "info": {
      "rate": 100
    },
    "grocery": [{
        "brand": "A",
        "brand_id": "983",
        myParent: function() {
          const that = this; // to fix the caller instead of using 'bind' or 'apply'
          return that;
        }
      },
      {
        "brand": "B",
        "brand_id": "253",
        myParent: function() {
          const that = this;
          return that;
        }
      }
    ],
    "discount": "20"
  }]
}
function myFunction() {
    let x = document.getElementById("myNumber").value;
    let text = myVar.prods[0].grocery.find(el => el.brand_id === x).myParent().brand; 
    document.getElementById("demo").innerHTML = text;
}
<input type="number" id="myNumber" value="253">
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>