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": "jsmith@test.com",
    "SortOrder": 1
  },
  {

    "ID": "125",
    "FirstName": "John",
    "LastName": "Doe",
    "Email": "jdoe@test.com",
    "SortOrder": 3
  },
  {

    "ID": "50",
    "FirstName": "james",
    "LastName": "johnson",
    "Email": "jjohnson@test.com",
    "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?

Tin
  • 424
  • 5
  • 13
JoAMoS
  • 1,459
  • 3
  • 18
  • 27
  • 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. – JoAMoS Mar 30 '17 at 20:28
  • Does this answer your question? [Select an array member by name with a JSON Pointer](https://stackoverflow.com/questions/41171075/select-an-array-member-by-name-with-a-json-pointer) – HairOfTheDog Mar 12 '21 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. – rakesh sinha Sep 22 '21 at 00:16

2 Answers2

29

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.

Community
  • 1
  • 1
Kipp
  • 711
  • 7
  • 10
  • 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. – Amala Sep 18 '20 at 22:05
  • Based on https://github.com/json-patch/json-patch2/issues/12 issue, JSON Patch only supports patching based on indexes—not dictionary attributes or query parameters. – mbigras Jun 07 '23 at 06:29
-3

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" }]
bl2b
  • 123
  • 4