Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set doesn't work out of the box for nested json that doesn't exist #26

Open
spangaer opened this issue Aug 8, 2016 · 0 comments
Open

Comments

@spangaer
Copy link

spangaer commented Aug 8, 2016

When trying to write a nested js:

{"a" : { "b" : "c"}}

using a single lens

val ab = 'a / 'b
JsObject.update(ab ! set("c"))

That fails.
So far I solved this with a rather poor solution, another combining operator:

trait EskoLenses extends ScalarLenses with OptionLenses with SeqLenses with Operations with JsonPathIntegration with ExtraImplicits {

  def writeIfAbscentCombine[M[_], M2[_], R[_]](outer: Lens[M], inner: Lens[M2])(implicit ev: Join[M2, M, R]): Lens[R] =
    new LensImpl[R]()(ev.get(inner.ops, outer.ops)) {
      def retr: JsValue => Validated[R[JsValue]] = parent =>
        for {
          outerV <- outer.retr(parent)
          innerV <- ops.allRight(outer.ops.flatMap(outerV)(x => inner.ops.toSeq(inner.retr(x))))
        } yield innerV

      def updated(f: SafeJsValue => SafeJsValue)(parent: JsValue): SafeJsValue =
        outer.updated {
          case l: Left[_, _] =>
            inner.updated(f)(JsObject())
          case r @ Right(js) =>
            inner.updated(f)(js)
        }(parent)
    }

}

object EskoLenses extends EskoLenses {
  implicit class WriteIfAbscenCombinator(outer: ScalarLens) {
    /**
     * When using this operator, the resulting lens join will not fail when trying to to do inner level writes, it will instead initialize an empty object
     *
     * @param inner
     * @return
     */
    def /?(inner: ScalarLens): ScalarLens = {
      EskoLenses.writeIfAbscentCombine(outer, inner)
    }
  }
}

I'm sure better solutions could be thought of.
E.g. a combining lens could be a class which can be matched against and from which the inner and outer can be recovered. That way the need for parent node creation could be detected and executed before attempting to write the nested json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant