21

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?

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. Commented Mar 30, 2017 at 20:28
  • Does this answer your question? Select an array member by name with a JSON Pointer Commented Mar 12, 2021 at 19:40
  • 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. Commented Sep 22, 2021 at 0:16

4 Answers 4

33

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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.
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.
2

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.

Comments

2

JSON Patch works exactly as your request if you change json from array to Map<ID, Object>

JSON Patch use index for array and key for map

1 Comment

I have no idea why you got downvoted! You saved me many hours of writing workaround code! Thank you so much! :D
-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" }]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.