JSON Modelling | Couchbase Docs (original) (raw)
The examples below assume you’re familiar with connecting to a Couchbase cluster using the Java SDK, and opening resources. Please check out the Getting Started guide for help with this.
Inserting a simple object
Let’s assume we have a very simple JSON structure we want to insert:
{
name: "Arthur",
number: 42
}
Once we’ve connected to a Couchbase server and the bucket, scope, and collection that we want to write to, we know that inserting is as simple as:
collection.upsert("arthur", json);
But how do we model that JSON object?
We mentioned the simple JSON library that we ship with the SDK, and let’s look at this first:
import com.couchbase.client.java.json.*;
JsonObject json = JsonObject.create()
.put("name", "Arthur")
.put("number", 42);
Retrieving
Couchbase’s Collection.get()
method returns a GetResult
object, which can then be converted back into a JsonObject
. In this example, we print the JSON back, and access one of the fields:
JsonObject jsonResult = collection.get("arthur")
.contentAsObject();
System.out.println(jsonResult);
System.out.println(jsonResult.getString("name"));
Using Java’s Map
data structure
The JsonObject
is modelled on the classic Java Map
data structure, and in fact is backed by one. So we can easily create an object from an existing Map:
Map<String, Object> map = Map.of( // Java 9+ syntax
"name", "Arthur",
"number", 42);
JsonObject json = JsonObject.from(map);
The resulting JsonObject
can be inserted as normal. But most JSON serializers can handle simple objects like a Map already, and ours (backed by Jackson) is no different. So you can simply:
collection.upsert("arthur", map);
Once the data is in Couchbase, it is stored in exactly the same way, that is to say, as the JSON representation we started this example with!
So whether we inserted a Map or a JsonObject, we could retrieve it as a JsonObject… or indeed a Map:
Map<String, Object> result = collection.get("arthur")
.contentAs(Map.class);
While you are free to use Map, this is capable of storing any valid Java value, including ones that can’t be represented as JSON. JsonObject offers validation to make sure that only the relevant datatypes are stored, which will give you greater diagnostics and robustness.
Inserting a JSON string or .json
file
If we read the contents of a file to get a JSON string, we can also inflate a JsonObject from that string:
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
String content = new String(
Files.readAllBytes(
Paths.get(pathToArthurJson)),
StandardCharsets.UTF_8);
// String content = Files.readString(Paths.get(pathToArthurJson), StandardCharsets.UTF_8); // Java 11+
JsonObject json = JsonObject.fromJson(content);
This might seem a little clumsy though: We’re reading a string, inflating it into a JsonObject, passing it to a serializer which will… turn it back into a string again to send over the network to the Couchbase server!
We could instead simply pass it through with the Raw JSON Transcoder:
import com.couchbase.client.java.codec.RawJsonTranscoder;
collection.upsert("arthur", content,
UpsertOptions.upsertOptions().transcoder(RawJsonTranscoder.INSTANCE));
This approach could also be used to handle JSON created by other libraries such as Gson. See the Transcoder documentation for more details.
Serializing objects
It’s common to want to serialize your own objects, rather than creating Json programmatically or textually. Luckily our built-in JSON serializer makes light work of this task. Using this simple class:
public class Person {
public String name;
public int number;
public Person() {} // default constructor needed to deserialize
public Person(String name, int number) {
this.name = name;
this.number = number;
}
}
We could insert the exact same JSON as before with:
collection.upsert("arthur", new Person("Arthur", 42));
It’s now trivial to return the data either as a JsonObject, exactly as we’ve done before, or indeed as a Person object:
Person person = collection.get("arthur")
.contentAs(Person.class);
More complex Object to JSON mapping
Because the SDK’s serializer is backed by an industry standard library (Jackson), it is easy to model all kinds of Object to JSON mappings. Though the SDK automatically uses your version of Jackson when it finds the library on the CLASSPATH, you may wish to be explicit, or use an already configured ObjectMapper, as in this example:
import com.couchbase.client.java.env.ClusterEnvironment;
import com.couchbase.client.java.codec.JacksonJsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JsonValueModule()); // for JsonObject
ClusterEnvironment env =
ClusterEnvironment.builder()
.jsonSerializer(JacksonJsonSerializer.create(mapper))
.build();
Cluster cluster = Cluster.connect(
connectionString,
ClusterOptions
.clusterOptions(username, password)
.environment(env));
With this setup, we can then configure our classes as we wish. Here, we’ve just renamed the Java class and its fields in Spanish. But the generated JSON will have the same fields as before, for easy interoperability:
public class Persona {
@JsonProperty("name")
public String nombre;
@JsonProperty("number")
public int numero;
// ...
}