JSON Get parent object from child object

2019-06-17 01:54发布

How can I get discount value if brand_id=='983'.

Sample JSON:

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

What I have tried till now is

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

This returns me list/array of matched objects. But I am not able to traverse back into the tree. Any help on this?

标签: json jsonpath
2条回答
女痞
2楼-- · 2019-06-17 02:04

Indeed, JSONPath isn't very good at that, so I tackled this kind of problem with my own small library; so, here's a fiddle for your example:

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

where:

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

gives:

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

Here are other examples / use cases:

JSON-to-some-markup

JSON transformations, revisited (XSLT look-alike)

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

JSON-to-JSON

Super-lightweight JSON-to-JSON transformations

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

A JavaScript equivalent of...

XSLT 3.0 REC Section 14.4 Example: Grouping Nodes based on Common Values

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

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

A JavaScript equivalent of...

JSONiq Use Cases Section 1.1.2. Grouping Queries for JSON

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

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

'Hope this helps,

查看更多
走好不送
3楼-- · 2019-06-17 02:17

You can write a function that returns the parent node. Once you have that, you should develop a function that walks (traverses) all the object and all its nodes and arrays, and when it finds the desired Id, well, you just get the parent and retrieve for the discount.

Here you have the simplest example of a function that returns the parent 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>

查看更多
登录 后发表回答