Created
December 16, 2020 15:55
-
-
Save gabrieljones/cd0d5104cf6f6573c51b56707063213b to your computer and use it in GitHub Desktop.
setAt, removeAt, withAt, withArrayAt for Jackson ObjectNodes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.fasterxml.jackson.core.JsonPointer | |
import com.fasterxml.jackson.databind.JsonNode | |
import com.fasterxml.jackson.databind.node.{ArrayNode, MissingNode, ObjectNode} | |
object JacksonExtension { | |
implicit class ObjectNodeExtension(val objectNode: ObjectNode) extends AnyVal { | |
def removeAt(jsonPtrExpr : String): JsonNode = removeAt(JsonPointer.compile(jsonPtrExpr)) | |
def removeAt(ptr: JsonPointer): JsonNode = { | |
(objectNode.at(ptr), objectNode.at(ptr.head)) match { | |
case (missing: MissingNode, _) => | |
missing | |
case (node, objectParent: ObjectNode) => | |
objectParent.remove(ptr.last.getMatchingProperty) | |
node | |
case (node, arrayParent: ArrayNode) => | |
arrayParent.remove(ptr.last.getMatchingIndex) | |
node | |
case (node, _) => | |
node | |
} | |
} | |
def withAt(jsonPtrExpr : String): JsonNode = withAt(JsonPointer.compile(jsonPtrExpr)) | |
def withAt(ptr: JsonPointer): JsonNode = { | |
(objectNode.at(ptr.head), ptr.last) match { | |
case (objectParent: ObjectNode, leaf) if leaf.mayMatchProperty() => | |
objectParent.`with`(ptr.last.getMatchingProperty) | |
case (arrayParent: ArrayNode, leaf) if leaf.mayMatchElement() => | |
throw new UnsupportedOperationException(s"Property `${ptr.head}` is an ArrayNode which is not currently supported, but could be, need to figure out padding") | |
case (missingParent: MissingNode, leaf) => | |
withAt(ptr.head()) // recursively materialize parent | |
withAt(ptr) //try again | |
case (otherParent, leaf) => | |
throw new UnsupportedOperationException(s"Property '${ptr.toString}' has value that is not of type ObjectNode (but ${otherParent.getClass.getName})") | |
} | |
} | |
def withArrayAt(jsonPtrExpr : String): JsonNode = withArrayAt(JsonPointer.compile(jsonPtrExpr)) | |
def withArrayAt(ptr: JsonPointer): JsonNode = { | |
(objectNode.at(ptr.head), ptr.last) match { | |
case (objectParent: ObjectNode, leaf) if leaf.mayMatchProperty() => | |
objectParent.withArray(ptr.last.getMatchingProperty) | |
case (arrayParent: ArrayNode, leaf) if leaf.mayMatchElement() => | |
throw new UnsupportedOperationException(s"Property `${ptr.head}` is an ArrayNode which is not currently supported, but could be, need to figure out padding") | |
case (missingParent: MissingNode, leaf) => | |
withArrayAt(ptr.head()) // recursively materialize parent | |
withArrayAt(ptr) //try again | |
case (otherParent, leaf) => | |
throw new UnsupportedOperationException(s"Property '${ptr.toString}' has value that is not of type ObjectNode or ArrayNode (but ${otherParent.getClass.getName})") | |
} | |
} | |
def setAt(jsonPtrExpr : String, value: JsonNode): JsonNode = setAt(JsonPointer.compile(jsonPtrExpr), value) | |
def setAt(ptr: JsonPointer, value: JsonNode): JsonNode = { | |
(objectNode.at(ptr.head), ptr.last) match { | |
case (objectParent: ObjectNode, leaf) if leaf.mayMatchProperty() => | |
objectParent.set(ptr.last.getMatchingProperty, value) | |
case (arrayParent: ArrayNode, leaf) if leaf.mayMatchElement() => | |
arrayParent.set(leaf.getMatchingIndex, value) | |
case (missingParent: MissingNode, leaf) if leaf.mayMatchProperty() => | |
withAt(ptr.head()) // recursively materialize parent | |
setAt(ptr, value) //try again | |
case (missingParent: MissingNode, leaf) if leaf.mayMatchElement() => | |
withArrayAt(ptr.head()) // recursively materialize parent | |
setAt(ptr, value) //try again | |
case (otherParent, leaf) if leaf.mayMatchElement() => | |
throw new UnsupportedOperationException(s"Property '${ptr.head.toString}' has value that is not of type ObjectNode or ArrayNode (but ${otherParent.getClass.getName})") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment