JSON
Goal
- Understand JSON syntax.
- Parse JSON documents using JSON.
Concepts
- associative array
- ECMAScript
- Extensible Markup Language (XML)
- JavaScript Object Notation (JSON)
Library
com.fasterxml.jackson.databind.JsonNode
com.fasterxml.jackson.databind.JsonNode.booleanValue()
com.fasterxml.jackson.databind.JsonNode.elements()
com.fasterxml.jackson.databind.JsonNode.get(int index)
com.fasterxml.jackson.databind.JsonNode.get(String fieldName)
com.fasterxml.jackson.databind.JsonNode.isObject()
com.fasterxml.jackson.databind.JsonNode.isTextual()
com.fasterxml.jackson.databind.JsonNode.textValue()
com.fasterxml.jackson.databind.JsonNode.getNodeType()
com.fasterxml.jackson.databind.ObjectMapper
com.fasterxml.jackson.databind.ObjectMapper.readTree(Reader r)
com.fasterxml.jackson.databind.ObjectMapper.readTree(String content)
com.fasterxml.jackson.databind.node.ArrayNode
com.fasterxml.jackson.databind.node.JsonNodeType
com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY
com.fasterxml.jackson.databind.node.JsonNodeType.BOOLEAN
com.fasterxml.jackson.databind.node.JsonNodeType.OBJECT
com.fasterxml.jackson.databind.node.JsonNodeType.STRING
com.fasterxml.jackson.databind.node.NullNode
com.fasterxml.jackson.databind.node.ObjectNode
Dependencies
Lesson
For well over a decade, the most popular text format for storing arbitrarily structured information has been the Extensible Markup Language (XML). Recently more and more Internet applications are switching to a newer format named JavaScript Object Notation (JSON). Taking some of the syntax of JavaScript for declaring values, JSON results in a leaner and simpler format that it easier to easier to generate, parse, and be read by humans.
JavaScript and Its Object Notation
The JavaScript language was created in 1995 and was originally intended for scripting in browsers. It is now standardized as ECMAScript. Although its common name contains the word Java
, it has little relation to the Java language other than its syntax (such as its use of the curly brace {
and }
characters). Unlike Java, JavaScript waits until a value is used to decide what type it is.
Douglas Crockford took the declarative syntax (that is, without any procedural logic) of the basic JavaScript types and defined them as a storage format, naming it the JavaScript Object Notation
. Because JSON data is essentially the declarative part of JavaScript , it can be evaluated by a JavaScript interpreter as if it were JavaScript code. This made it easy to be parsed in browsers when and helped JSON become popular.
JSON is defined both by RFC 7159 and by ECMA-404 from Ecma International. JSON data contains one of JavaScript's value types, but that single value may recursively contain other values.
Numbers
JavaScript numbers as used by JSON is similar to basic Java number literals, with optional numbers after a decimal point. Hexadecimal and octal are not allowed. Here are some examples.
1234
-1234
12.34
12.3e+4
Strings
Strings in JavaScript are also very similar to string literals, including the use of the backslash \
character for escaping. Here are some examples:
""
"abc"
"abc\ndef"
"The Hindi letter \u092E starts with the consonant \"m\" sound."
Other Values
JavaScript and JSON also allow these special values. As with all JavaScript values, you don't have to indicate their type.
true
false
null
Arrays
Representing an array in JavaScript syntax is simpler than in Java. Simply place values inside bracket [
]
characters, separated by commas. The types can be mixed, as they are not specified at declaration time in JavaScript. Here are some examples:
[]
[1, 2, 3]
[123, true, 123.4, false, true, "false", null]
[123, ["foo", "bar"], true]
Objects
The central construct for encapsulating data in JavaScript is an "object". In JavaScript an object is essentially a collection of name/value associations; it is technically referred to as an associative array. It conceptually performs the same function as the Map<K, V>
interface.
The "keys" of a JavaScript object are strings; the values can be any values, including other objects. Each named key and its value are separated by a colon :
character, while each name/value pair is separated by the comma ,
character. Here are some examples of objects.
{}
{"foo":"bar"}
{"example":123}
{"example":{"foo":"bar"}}
{"test":[123, ["foo", "bar"], true, {"foo":"bar","foobar":456.789}]}
Parsing JSON Using Jackson
There are several libraries available for parsing JSON using Java. Besides one of the early implementations org.json
, two of the most popular packages are gson (from Google) and Jackson. In this lesson we will use Jackson, which is well established and is widely used as a plugin in certain Internet-based frameworks.
Jackson offers three different approaches to choose from when parsing JSON:
- tree model
- Parses the entire JSON document and provides it as a tree structure.
- streaming API
- Provides events to your code as sections of the JSON document is parsed.
- data binding
- Automatically converts objects to and from JSON based on some mapping.
Tree Model
In future lessons you'll learn how to use Jackson data binding in Internet-based services. For now you will use the tree model. Although it is not as memory efficient as the streaming API, it is simpler in that it mostly closely resembles the JSON structure as viewed in a formatted text file.
To parse JSON into a tree using Jackson, create a com.fasterxml.jackson.databind.ObjectMapper
instance. The ObjectMapper.readTree(Reader r)
method will return a tree structure with the root node an instance of com.fasterxml.jackson.databind.JsonNode
representing the main JSON object. The JsonNode
provides access to the entire tree of JSON values, each represented as another JsonNode
. Because JSON allows many different types of values, you'll need to check the type of the node's type using JsonNode.getNodeType()
. The returned com.fasterxml.jackson.databind.node.
JsonNodeType enum instance indicates whether the node is a JsonNodeType.OBJECT
, a JsonNodeType.ARRAY
, or one of the other enum instances representing JSON value types.
Once you know the value type the node represents, you can retrieve a primitive value using a method such as JsonNode.booleanValue()
for type JsonNodeType.BOOLEAN
; or JsonNode.textValue()
for JsonNodeType.STRING
. You can access array elements using JsonNode.get(int index)
or JsonNode.elements()
; and access object values associated with keys using JsonNode.get(String fieldName)
.
There are many other methods for accessing JSON data from the parsed tree, and you should read the API documentation before using Jackson and keep it handy as a reference later. The following example code shows how to parse a sample JSON document from a string using ObjectMapper.readTree(String content)
:
Review
Gotchas
- JSON object name value associates must be separated by commas. Don't forget the comma in
{"foo": 123, "bar": 456}
for example. - If you represent a JSON string inside a Java string, don't forget to escape the JSON escape characters for Java—that is, doubly escape certain characters.
In the Real World
- JSON is becoming very popular for sending information between a client server. You'll find it being used as a configuration file format as well.
Self Evaluation
- What relationship does JSON have to JavaScript?
- Can you parse JSON as JavaScript? Would you want to?
- How can special characters be escaped in JSON strings, and how does this relate to Java?
Task
Improve the Booker ISBN lookup so that instead of printing out the literal response from the Google Books API lookup request, it parses the JSON response using Jackson and creates a Book
instance and stores it in the repository. In other words, when Booker is started with the list
command and the --lookup
option:
- Booker will retrieve the JSON information for the book using the Google Books API.
- Booker will find the relevant information from the JSON object tree and create an instance of
Book
. - Booker will store this new book in the current repository.
- Booker will then display the book information from the repository as it normally would for the
list
command.
Include at least the following information from the JSON object tree in the new book instance:
- title
- author(s)
- publisher
- publish year
See Also
References
- ECMA-404: The JSON Data Interchange Format
- RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format
- jackson-core 2.8.0 API
- jackson-databind 2.8.0 API
Resources
Acknowledgments
- JSON syntax diagrams Copyright © 2002 JSON.org and used by permission in the JSON license.
- Some symbols are from Font Awesome by Dave Gandy.