How to find value with dynamic node name using Jackson and JsonPointer
I don't think the JsonPointer specification supports wildcards. It's pretty basic. Instead you can consider using JsonPath with the Jackson mapping provider. Here is an example:
public class JacksonJsonPath {
public static void main(String[] args) {
final ObjectMapper objectMapper = new ObjectMapper();
final Configuration config = Configuration.builder()
.jsonProvider(new JacksonJsonNodeJsonProvider())
.mappingProvider(new JacksonMappingProvider())
.build();
// { "root" : { "dynamic123" : "Some value" } }
ObjectNode json = objectMapper.createObjectNode();
json.set("root", json.objectNode().put("dynamic123", "Some value"));
final ArrayNode result = JsonPath
.using(config)
.parse(json).read("$.root.*", ArrayNode.class);
System.out.println(result.get(0).asText());
}
}
Output:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Some value
Related videos on Youtube
wassgren
Experienced agile leader with strong technical background and a sweet spot for new technology. Specialties include technical recruitment, technical mentoring, software development, project management, sales and online marketing. Somewhat fluent in full stack development including UX, information architecture, frontend- and backend development, designing API:s, Continuous Delivery etc. Preferred programming languages and technologies include JavaScript, Node.js, Serverless, AWS, NoSQL such as Redis/Neo4j and a wide variety of frontend- and mobile technologies.
Updated on September 20, 2022Comments
-
wassgren over 1 year
I am using Jackson (version 2.6+) to parse some ugly JSON that looks like this:
{ "root" : { "dynamic123" : "Some value" } }
The name of the attribute
dynamic123
is unfortunately not known until runtime and may differ from time to time. What I am trying to achieve is to use JsonPointer to get to the value"Some value"
. JsonPointer uses an XPath-like syntax that is described here.// { "root" : { "dynamic123" : "Some value" } } ObjectNode json = mapper.createObjectNode(); json.set("root", json.objectNode().put("dynamic123", "Some value")); // Some basics JsonNode document = json.at(""); // Ok, the entire document JsonNode missing = json.at("/missing"); // MissingNode (as expected) JsonNode root = json.at("/root"); // Ok -> { dynamic123 : "Some value" } // Now, how do I get a hold of the value under "dynamic123" when I don't // know the name of the node (since it is dynamic) JsonNode obvious = json.at("/root/dynamic123"); // Duh, works. But the attribute name is unfortunately unknown so I can't use this JsonNode rootWithSlash = json.at("/root/"); // MissingNode, does not work JsonNode zeroIndex = json.at("/root[0]"); // MissingNode, not an array JsonNode zeroIndexAfterSlash = json.at("/root/[0]"); // MissingNode, does not work
So, now to my question. Is there a way of retrieving the value
"Some value"
using JsonPointer?Obviously there are other ways of retrieving the value. One possible approach is to use the
JsonNode
traversal functions – e.g. like this:JsonNode root = json.at("/root"); JsonNode value = Optional.of(root) .filter(d -> d.fieldNames().hasNext()) // verify that there are any entries .map(d -> d.fieldNames().next()) // get hold of the dynamic name .map(name -> root.get(name)) // lookup of the value .orElse(MissingNode.getInstance()); // if it is missing
But, I am trying to avoid traversal and only use JsonPointer.
-
wassgrenThanks @watery, unfortunately this is not XPath (but slightly similar to XPath). This is a separate spec and the
/root/*[1]
does not work.
-