The license of this project is LGPLv3 or later. See file src/main/resources/LICENSE for the full
text.
This project uses Gradle as a build system. See file BUILD.md for
details.
Credits where they are due: other people have contributed to this project, and this project would
not have reached its current state without them. Please refer to the CONTRIBUTORS.md file in this
project for details.
This package is meant to be used with Jackson 2.2.x. It provides the three following features:
- its
JsonLoaderclass brings you a convenient way for loading JSON data from a variety of sources: a string, an existingInputStreamorReader, etc; - it uses Guava's Equivalence over Jackson's JsonNode to provide a means to compare JSON number values mathematically;
- it implements JSON Pointer
over Jackson's
TreeNode, and has a dedicated implementation (JsonPointer) over Jackson'sJsonNode.
The current verson is 1.4. Its Javadoc is available online.
With Gradle:
dependencies {
compile(group: "com.github.fge", name: "jackson-coreutils", version: "yourVersionHere");
}With Maven:
<dependency>
<groupId>com.github.fge</groupId>
<artifactId>jackson-coreutils</artifactId>
<version>yourVersionHere</version>
</dependency>When reading JSON into a JsonNode, Jackson will serialize 1 as an IntNode but 1.0 as a
DoubleNode (or a DecimalNode).
Understandably so, Jackson will not consider such nodes to be equal, since they do not share the same class. But, understandably so as well, some uses of JSON out there, including JSON Schema and JSON Patch, want to consider such nodes as equal.
And this is where this package comes in. It allows you to consider that two numeric JSON values are
mathematically equal -- recursively so. That is, JSON values 1 and 1.0 will be considered
equivalent; but so will be all possible JSON representations of mathematical value 1 (including, for
instance, 10e-1). And evaluation is recursive, which means that:
[ 1, 2, 3 ]will be considered equivalent to:
[ 10e-1, 2.0, 0.3e1 ]JSON Pointer is an IETF draft which allows to unambiguously address any value into a JSON document (including the document itself, with the empty pointer). It is used in several IETF drafts:
- JSON Reference (as the fragment part);
- JSON Patch.
The implementation in this package applies to all TreeNodes as of Jackson 2.2.x.
For accuracy, it is highly recommended that you use this library's JacksonUtils class to
obtain a mapper/reader with the ability to read arbitrarily large numeric instances from JSON
values; if you don't, you may be (badly) surprised by the results of using the below feature.
The recommended way to read any JsonNode instance is therefore to use the JsonLoader class, or,
if you need to, grab an ObjectMapper preconfigured for dealing with arbitrarily large numbers:
// Load a JsonNode with all decimals read as DecimalNode, from a file
final JsonNode node = JsonLoader.fromFile("/path/to/file.json");
// Get a preconfigured reader
final ObjectReader reader = JacksonUtils.getReader();
// Get a preconfigured ObjectMapper
final ObjectMapper mapper = JacksonUtils.newMapper();Given two JsonNode instances which you want to be equivalent if their JSON number values are the
same, you can use:
if (JsonNumEquals.getInstance().equivalent(node1, node2))
// do somethingYou can also use this package to add JsonNode instances to a set:
final Equivalence<JsonNode> eq = JsonNumEquals.getInstance();
// Note: uses Guava's Sets to create the set
final Set<Equivalence.Wrapper<JsonNode>> set
= Sets.newHashSet();
// Insert values
set.add(eq.wrap(node1));
set.add(eq.wrap(node2));
// etcThis section concentrates on the JsonNode specific JSON Pointer implementation: JsonNode.
There are several ways you can build one:
// Build from an input string -- potentially throws JsonPointerException on malformed inputs
final JsonPointer ptr = new JsonPointer("/foo/bar");
// Build from a series of raw tokens
final JsonPointer ptr = JsonPointer.of("foo", "bar", 1); // Yields pointer "/foo/bar/1"
// Get another pointer's parent:
final JsonPointer parent = ptr.parent();Note that JsonPointer (and, for that matter, TreePointer as well) is immutable:
// DON'T DO THAT: value of "ptr" will not change
ptr.append("foo");
// Do that instead
ptr = ptr.append("foo");