wI2L / jsondiff

Compute the diff between two JSON documents as a series of RFC6902 (JSON Patch) operations
https://pkg.go.dev/github.com/wI2L/jsondiff
MIT License
522 stars 41 forks source link

I am looking for a Stronger jsonPatch apply lib #1

Closed zhangguanzhang closed 3 years ago

zhangguanzhang commented 3 years ago

usefor Kubernetes Dynamic Admission Controller

package main

import (
    "encoding/json"
    "fmt"

    jsonpatch "github.com/xxxx/json-patch"
    corev1 "k8s.io/api/core/v1"

)

func main()  {

    var pod = corev1.Pod{
        Spec:       corev1.PodSpec{
            Volumes: []corev1.Volume{
                {
                    Name: "default-token-lsh6v",
                    VolumeSource: corev1.VolumeSource{
                        Secret: &corev1.SecretVolumeSource{
                            SecretName: "default-token-lsh6v",
                        },
                    },
                },
            },

        },
    }

    podBytes, _ := json.Marshal(&pod)

    fmt.Printf("old document: %s\n", podBytes)

    patchJSON := []byte(`[
   {
      "op":"add",
      "path":"/spec",
      "value":{
         "dnsConfig":{
            "options":[
               {
                  "name":"single-request-reopen"
               }
            ]
         }
      }
   },
   {
      "op":"add",
      "path":"/spec/volumes/-",
      "value":{
         "name":"default-token-lsh6v1111",
         "secret":{
            "secretName":"default-token-lsh6v1111"
         }
      }
   }
]`)
    patch, err := jsonpatch.DecodePatch(patchJSON)
    if err != nil {
        panic(err)
    }
    modified, err := patch.Apply(podBytes)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Modified document: %s\n", modified)

}

expect result json is:

{
   "metadata":{
      "creationTimestamp":null
   },
   "spec":{
      "dnsConfig":{
         "options":[
            {
               "name":"single-request-reopen"
            }
         ]
      },
      "containers":null,
      "volumes":[
         {
            "name":"default-token-lsh6v",
            "secret":{
               "secretName":"default-token-lsh6v"
            }
         },
         {
            "name":"default-token-lsh6v1111",
            "secret":{
               "secretName":"default-token-lsh6v1111"
            }
         }
      ]
   }
}

also, I expect:

   {
      "op":"append",
      "path":"/spec/containers/*/env",
      "value":{
         "name":"KEY",
         "value": "VALUE"
      }
   }

this will append a env to all containers ,not override

wI2L commented 3 years ago

This package is for generating JSON Patches, not applying them, so I'm not sure what's your question. Moreover, the append OP isn't specified by the JSON Patch RFC, you should use an add operation with a path like /path/to/element/- to append a the end of an array.

zhangguanzhang commented 3 years ago

the first op add will add a dnsConfig to override spec.

wI2L commented 3 years ago

Sorry, is this related to this package ? I still can't tell from your question. Are you generating a patch with jsondiff ?

zhangguanzhang commented 3 years ago

patch:

[
   {
      "op":"add",
      "path":"/bar",
      "value":{
         "test111111111":{
            "a":1,
            "b":2
         }
      }
   }
]

data:

{
  "bar" : {
    "test": 1
    }
}

result:

{
  "bar" : {
    "test111111111" : {
      "a" : 1,
      "b" : 2
    }
  }
}

I expect there has a stronger JsonPatch lib to get this result:

{
  "bar" : {
    "test": 1,
    "test111111111" : {
      "a" : 1,
      "b" : 2
    }
  }
}
zhangguanzhang commented 3 years ago

Assuming that there is a super jsonPatch language, we can use it to change the json of the pod, and then use jsonDiff to generate a regular jsonPatch. The user only needs to write this super jsonPatch to change the properties of the pod in the access control of the pod.

wI2L commented 3 years ago

Your patch is valid, see https://tools.ietf.org/html/rfc6902#section-4.1

If the target location specifies an object member that does exist, that member's value is replaced.

I still don't get the link between your issue and this package.

zhangguanzhang commented 3 years ago

I know this, I mean you can construct a middle-layer jsonPatch, and finally generate a standard jsonPatch

wI2L commented 3 years ago

I still don't get what is your point. Are you reporting an issue with the package, or proposing a feature ? You are talking about a "super jsonPatch", but that seems hypothetical to me, there's no such thing that I'm aware of. This package follows the JSON Patch RFC.

Please provide a full explanation of what your trying to achieve, and why, so I can understand what we're talking about, otherwise I won't be able to provide a constructive answer.

Thanks