Oracle NoSQL Database
version 11gR2.2.0.26

oracle.kv.avro
Interface JsonAvroBinding

All Superinterfaces:
AvroBinding<JsonRecord>, ValueBinding<JsonRecord>

public interface JsonAvroBinding
extends AvroBinding<JsonRecord>

The JsonAvroBinding interface has the same methods as AvroBinding, but represents values as instances of JsonRecord. A single schema binding is created using AvroCatalog.getJsonBinding(org.apache.avro.Schema), and a multiple schema binding is created using AvroCatalog.getJsonMultiBinding(java.util.Map).

The trade-offs in using a JsonAvroBinding, compared to other types of bindings, are:

See AvroCatalog for general information on Avro bindings and schemas. The schemas used in the examples below are described in the AvroCatalog javadoc.

When using a JsonAvroBinding, a JsonRecord is used to represent values. A JsonRecord represents an Avro object as an JsonNode in the Jackson API.

As with a generic binding, a JsonNode represents an Avro object roughly as a map of string field names to field values. However, the Jackson API is very rich and fully supports the JSON format. For those familiar with XML, the Jackson API is for JSON what the DOM API is for XML. JSON text may also be easily parsed and formatted using the Jackson API.

The following code fragment demonstrates writing and reading a value using a JSON single schema binding.

 Schema.Parser parser = new Schema.Parser();
 Schema nameSchema = parser.parse(nameSchemaText);
 Schema memberSchema = parser.parse(memberSchemaText);

 JsonAvroBinding binding = avroCatalog.getJsonBinding(memberSchema);

 // Create object
 ObjectNode member = JsonNodeFactory.instance.objectNode();
 JsonRecord object = new JsonRecord(member, memberSchema)
 ObjectNode name = member.putObject("name");
 name.put("first", ...);
 name.put("last", ...);
 member.put("age", ...);

 // Serialize and store
 Value value = binding.toValue(object);
 kvStore.put(key, value);

 // Sometime later, retrieve and deserialize
 ValueVersion vv = kvStore.get(key);
 JsonRecord object = binding.toObject(vv.getValue());

 // Use object
 ObjectNode member = (ObjectNode) object.getNode();
 ObjectNode name = (ObjectNode) member.get("name");
 int age = member.get("age").getIntValue();
 ...

The following code fragment demonstrates reading values with different schemas using a JSON multiple schema binding.

 Schema.Parser parser = new Schema.Parser();
 Schema nameSchema = parser.parse(nameSchemaText);
 Schema memberSchema = parser.parse(memberSchemaText);
 Schema anotherSchema = parser.parse(anotherSchemaText);

 Map<String, Schema> schemas = new HashMap<String, Schema>()
 schemas.put(memberSchema.getFullName(), memberSchema);
 schemas.put(anotherSchema.getFullName(), anotherSchema);

 JsonAvroBinding binding = avroCatalog.getJsonMultiBinding(schemas);

 Iterator<KeyValueVersion> iter = kvStore.multiGetIterator(...);
 for (KeyValueVersion kvv : iter) {
     JsonRecord object = binding.toObject(kvv.getValue());
     JsonNode jsonNode = object.getJsonNode();
     String schemaName = object.getSchema().getFullName();
     if (schemaName.equals(memberSchema.getFullName())) {
         ...
     } else if (schemaName.equals(anotherSchema.getFullName())) {
         ...
     } else {
         ...
     }
 }

A special use case for a JSON multiple schema binding is when the application treats values dynamically based on their schema, rather than using a fixed set of known schemas. The AvroCatalog.getCurrentSchemas() method can be used to obtain a map of the most current schemas, which can be passed to AvroCatalog.getJsonMultiBinding(java.util.Map).

For example, the following code fragment demonstrates reading values with different schemas using a JSON multiple schema binding. Note that in a long running application, it is possible that a schema may be added and used to store a key-value pair, after the binding has been created. The application may handle this possibility by catching SchemaNotAllowedException.

 JsonAvroBinding binding =
     avroCatalog.getJsonMultiBinding(avroCatalog.getCurrentSchemas());

 Iterator<KeyValueVersion> iter = kvStore.storeIterator(...);
 for (KeyValueVersion kvv : iter) {
     JsonRecord object;
     try {
         object = binding.toObject(kvv.getValue());
     } catch (SchemaNotAllowedException e) {
         // In this example, ignore values with a schema that was not
         // known at the time the binding was created.
         continue;
     }
     JsonNode jsonNode = object.getJsonNode();
     String schemaName = object.getSchema().getFullName();
     if (schemaName.equals(memberSchema.getFullName())) {
         ...
     } else if (schemaName.equals(anotherSchema.getFullName())) {
         ...
     } else {
         ...
     }
 }

Since:
2.0

Method Summary
 JsonRecord toObject(Value value)
          After doing a read operation using a KVStore method, the user calls toObject with the Value obtained from the read operation.
 Value toValue(JsonRecord object)
          Before doing a write operation, the user calls toValue passing an object she wishes to store.
 

Method Detail

toObject

JsonRecord toObject(Value value)
                    throws SchemaNotAllowedException,
                           IllegalArgumentException
After doing a read operation using a KVStore method, the user calls toObject with the Value obtained from the read operation.

If necessary, this method automatically performs schema evolution, as described in AvroCatalog. In the context of schema evolution, the writer schema is the one associated internally with the value parameter (this association was normally made earlier when the value was stored), and the reader schema is the one associated with this binding (and was specified when the binding was created).

In other words, this method transforms the serialized data in the value parameter to conform to the schema of the JsonRecord that is returned.

Specified by:
toObject in interface AvroBinding<JsonRecord>
Specified by:
toObject in interface ValueBinding<JsonRecord>
Parameters:
value - the Value obtained from a KVStore read operation method.. The byte array of the Value is serialized Avro data, packaged in an internal format that includes a reference to the Avro schema
Returns:
the deserialized JsonRecord instance. The JsonRecord.getSchema() method will return the reader schema, which is the schema that was specified when this binding was created.
Throws:
SchemaNotAllowedException - if the schema associated with the value parameter is not allowed with this binding.
IllegalArgumentException - if the value format is not Value.Format.AVRO, the schema identifier embedded in the value parameter is invalid, or the serialized data cannot be parsed.

toValue

Value toValue(JsonRecord object)
              throws SchemaNotAllowedException,
                     UndefinedSchemaException,
                     IllegalArgumentException
Before doing a write operation, the user calls toValue passing an object she wishes to store. The resulting Value is then passed to the write operation method in KVStore.

In the context of schema evolution, as described in AvroCatalog, the returned value is serialized according to the writer schema. The writer schema is the one associated with the JsonRecord object parameter; it is returned by JsonRecord.getSchema() and specified when creating a JsonRecord object. The writer schema must be one of the schemas specified when this binding was created.

In other words, this method returns serialized data that conforms to the schema of the given JsonRecord.

Specified by:
toValue in interface AvroBinding<JsonRecord>
Specified by:
toValue in interface ValueBinding<JsonRecord>
Parameters:
object - the JsonRecord instance the user wishes to store, or at least serialize.
Returns:
the serialized object.. The byte array of the Value is serialized Avro data, packaged in an internal format that includes a reference to the Avro schema
Throws:
SchemaNotAllowedException - if the schema associated with the object parameter is not allowed with this binding.
UndefinedSchemaException - if the schema associated with the object parameter has not been defined using the NoSQL Database administration interface. Note that when the allowed schemas for a binding are specified (and validate) at the time the binding is created, this exception is extremely unlikely and is only possible if a schema is mistakenly disabled after the binding is created.
IllegalArgumentException - if the object parameter is invalid according to its schema, and cannot be serialized.

Oracle NoSQL Database
version 11gR2.2.0.26

Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved.