qri-io / jsonpointer

golang implementation of IETF RFC6901: https://tools.ietf.org/html/rfc6901
MIT License
16 stars 3 forks source link

Ability to modify value in a document using Pointer #11

Open gobwas opened 2 years ago

gobwas commented 2 years ago

Hello there,

Thank you for such clean and simple library!

What feature or capability would you like?

I'd like to have an ability to have a call like pointer.Set(interface{}). E.g., if we treat pointer.Eval() as Get method, it would be great to have a Set version as well.

Do you have a proposed solution?

Yes, probably some recursive (or just a bit more if-hairy iteration) over pointer parts -- we should be aware of the latest part in the pointer and set its value in a document instead of accessing it.

Have you considered any alternative solutions or workarounds?

Yes.

gobwas commented 2 years ago

As a reference this modified evalToken() can be used to have this feature:

  func evalPointer(data interface{}, p jsonpointer.Pointer, v interface{}) (prev interface{}, err error) {
      if len(p) == 0 {
          return nil, fmt.Errorf("empty reference pointer")
      }
      var (
          set = len(p) == 1
          tok = p[0]
      )
      switch c := data.(type) {
      case map[string]interface{}:
          if set {
              prev = c[tok]
              c[tok] = v
              return prev, nil
          }
          return evalPointer(c[tok], p[1:], v)

      case []interface{}:
          i, err := strconv.Atoi(tok)
          if err != nil {
              return nil, fmt.Errorf("invalid array index: %s", tok)
          }
          if i >= len(c) {
              return nil, fmt.Errorf("index %d exceeds array length of %d", i, len(c))
          }
          if set {
              prev = c[i]
              c[i] = v
              return prev, nil
          }
          return evalPointer(c[i], p[1:], v)

      default:
          return nil, fmt.Errorf("invalid reference pointer part: %q", tok)
      }
  }