jsonpatch path to update array object by object ID
Asked Answered
H

3

19

I am trying to figure out the best way to patch a collection of objects. I am trying to change the sort order of a number of objects and was thinking jsonpatch may be the right approach. My Object Looks Like:

[
  {
    "ID": "100",
    "FirstName": "John",
    "LastName": "Smith",
    "Email": "[email protected]",
    "SortOrder": 1
  },
  {

    "ID": "125",
    "FirstName": "John",
    "LastName": "Doe",
    "Email": "[email protected]",
    "SortOrder": 3
  },
  {

    "ID": "50",
    "FirstName": "james",
    "LastName": "johnson",
    "Email": "[email protected]",
    "SortOrder": 2
  },
]

I created an endpoint that allows a patch request to update multiple objects in the collection using jsonpatch request like this:

[
  {
    "op": "replace",
    "path": "/1/SortOrder",
    "value": 2
  },
  {
    "op": "replace",
    "path": "/0/SortOrder",
    "value": 1
  },
  {
    "op": "replace",
    "path": "/2/SortOrder",
    "value": 3
  }
]

What I want to be able to do is use the ID property in the jsonpatch path. Is that possible with my current object structure? It would look something like:

[
  {
    "op": "replace",
    "path": "/125/SortOrder",
    "value": 2
  },
  {
    "op": "replace",
    "path": "/100/SortOrder",
    "value": 1
  },
  {
    "op": "replace",
    "path": "/50/SortOrder",
    "value": 3
  }
]

What would I have to do to be able to make a patch request like this?

Handling answered 24/3, 2017 at 21:22 Comment(3)
I think the only way to do what I am asking is to use a dictionary rather than an array. The problem I am running into now is that my key value is a guid and it seems that the jsonpatch implementation in .NET are not a fan of guid keys.Handling
Does this answer your question? Select an array member by name with a JSON PointerHousum
If this helps -> I pass the Id of my object in the request URL, and then apply PATCH on the object retrieved from that id.Dupree
T
31

Based on the Json pointer RFC, there is no way to select an element from an array by some property. Since JSON Patch uses JSON Pointer, you are out of luck.

It is too bad the JSON Patch folks didn't select JSON Path, or something similar, for the selection language.

Torr answered 7/4, 2017 at 23:55 Comment(2)
I don't think this is correct. I realize no examples of array indexes are given in the JSON Patch specification, but the JSON Pointer RFC does mention array values.Duky
Based on github.com/json-patch/json-patch2/issues/12 issue, JSON Patch only supports patching based on indexes—not dictionary attributes or query parameters.Merari
M
0

You can avoid using arrays and just rely on JSON objects. It's not exactly ideal, but you can still rely on jsonpointers really nicely.

So your original document would change to look like:

{
  "100": {
    "ID": "100",
    "FirstName": "John",
    "LastName": "Smith",
    "Email": "[email protected]",
    "SortOrder": 1
  },
  "125": {
    "ID": "125",
    "FirstName": "John",
    "LastName": "Doe",
    "Email": "[email protected]",
    "SortOrder": 3
  },
  "50": {
    "ID": "50",
    "FirstName": "james",
    "LastName": "johnson",
    "Email": "[email protected]",
    "SortOrder": 2
  }
}

Then your JSON PATCH payload can look like:

[
  {
    "op": "replace",
    "path": "/125/SortOrder",
    "value": 2
  },
  {
    "op": "replace",
    "path": "/100/SortOrder",
    "value": 1
  },
  {
    "op": "replace",
    "path": "/50/SortOrder",
    "value": 3
  }
]

If you care about ordering in your JSON array, you can introduce a new field "position" or "index" or whatever you like to maintain ordering.

Meletius answered 29/2 at 1:8 Comment(0)
G
-4

try this function:

export function generateJsonPatch(obj: Object, patchObject = [], parent: string = null): Object[] {
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (obj[key] instanceof Object) {
        if (parent) {
          parent = parent + '/' + key;
        } else {
          parent = key;
        }
        generateJsonPatch(obj[key], patchObject, parent);
      } else if (obj[key]) {
        let fieldName;
        if (parent) {
          fieldName = parent + '/' + key;
        } else {
          fieldName = key;
        }
        const patchField = { op: 'replace', path: `/${fieldName}`, value: `${obj[key]}` };
        patchObject.push(patchField);
      }
    }
  }
  return patchObject;
}

// USAGE:
const test = {
  'a': '1',
  'b': '2',
  'c': [{
    'd': '4',
    'e': '5'
  }]
};

generateJsonPatch(test);
// it will generate
// [{ "op": "replace", "path": "/a", "value": "1" },
//  { "op": "replace", "path": "/b", "value": "2" },
//  { "op": "replace", "path": "/c/0/d", "value": "4" },
//  { "op": "replace", "path": "/c/1/e", "value": "5" }]
Gezira answered 19/8, 2018 at 11:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.