All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kv-4.0.9.src.oracle.kv.avro.JsonAvroBinding Maven / Gradle / Ivy

Go to download

Oracle NoSQL Database Client - supplies build and runtime support for the client side of the Oracle NoSQL Database. Note that a running Oracle NoSQL Database Server (store) is required to do anything meaningful with this client.

There is a newer version: 18.3.10
Show newest version
/*-
 *
 *  This file is part of Oracle NoSQL Database
 *  Copyright (C) 2011, 2016 Oracle and/or its affiliates.  All rights reserved.
 *
 * If you have received this file as part of Oracle NoSQL Database the
 * following applies to the work as a whole:
 *
 *   Oracle NoSQL Database server software is free software: you can
 *   redistribute it and/or modify it under the terms of the GNU Affero
 *   General Public License as published by the Free Software Foundation,
 *   version 3.
 *
 *   Oracle NoSQL Database is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Affero General Public License for more details.
 *
 * If you have received this file as part of Oracle NoSQL Database Client or
 * distributed separately the following applies:
 *
 *   Oracle NoSQL Database client software is free software: you can
 *   redistribute it and/or modify it under the terms of the Apache License
 *   as published by the Apache Software Foundation, version 2.0.
 *
 * You should have received a copy of the GNU Affero General Public License
 * and/or the Apache License in the LICENSE file along with Oracle NoSQL
 * Database client or server distribution.  If not, see
 * 
 * or
 * .
 *
 * An active Oracle commercial licensing agreement for this product supersedes
 * these licenses and in such case the license notices, but not the copyright
 * notice, may be removed by you in connection with your distribution that is
 * in accordance with the commercial licensing terms.
 *
 * For more information please contact:
 *
 * [email protected]
 *
 */

package oracle.kv.avro;

import oracle.kv.Value;

import org.apache.avro.Schema;
import org.apache.avro.generic.GenericRecord;
import org.codehaus.jackson.JsonNode;

/**
 * The {@code JsonAvroBinding} interface has the same methods as {@link
 * AvroBinding}, but represents values as instances of {@link JsonRecord}.
 * A single schema binding is created using {@link
 * AvroCatalog#getJsonBinding}, and a multiple schema binding is created
 * using {@link AvroCatalog#getJsonMultiBinding}.
 * 

* The trade-offs in using a {@code JsonAvroBinding}, compared to other types * of bindings, are: *

    *
  • Probably the most important reason for using a JSON binding is for * interoperability with other components or external systems that use JSON * objects. *

  • *
  • Like generic bindings, an advantage of using a JSON binding is that * values may be treated generically. Also, if schemas are treated * dynamically, then the set of schemas used in the application need not be * fixed at build time. *

  • *
  • Unlike {@link GenericRecord}, certain Avro data types are not * represented conveniently using JSON syntax, namely: *
      *
    • Avro {@code int} and {@code long} are both represented as a JSON * {@code integer}, and Avro {@code float} and {@code double} are both * represented as a JSON {@code number}. WARNING: To avoid type conversion * errors, consider defining integer fields in the Avro schema using type * {@code long}, and floating point fields using type {@code double}.
    • *
    • Avro {@code bytes} and {@code fixed} are both represented as a * JSON {@code string}, using Unicode escape syntax. WARNING: Characters * greater than {@code 0xFF} are invalid because they cannot be translated * to bytes without loss of information. Also note that the Jackson * {@link org.codehaus.jackson.node.BinaryNode} class is not * used with these Avro types.
    • *
    • Avro unions have a special * JSON representation.
    • *
    * Therefore, applications using JSON should limit the data types used in * their Avro schemas, and should treat the above data types carefully. *

    * Also note the following type mappings: *

      *
    • Avro {@code record} and {@code map} are both represented as a JSON * {@code object}.
    • *
    • An Avro {@code enum} is represented as a JSON {@code string}.
    • *
    *

  • *
  • Like a {@link GenericRecord}, a JSON object does not provide type * safety. It can also be error prone, because fields are accessed by * string name. *

  • *
  • To support class evolution, with JSON bindings (like generic * bindings, but unlike specific bindings) the application must supply the * Avro {@link Schema} objects at runtime. In other words, the application * must maintain a set of known schemas for use at runtime. *

  • *
*

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

* When using a {@code JsonAvroBinding}, a {@link JsonRecord} is used to * represent values. A {@link JsonRecord} represents an Avro object as an * {@link JsonNode} in the Jackson API. *

* As with a generic binding, a {@link 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 {@link * AvroCatalog#getCurrentSchemas} method can be used to obtain a map of the * most current schemas, which can be passed to {@link * AvroCatalog#getJsonMultiBinding}. *

* 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 {@link 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 * * @deprecated as of 4.0, use the table API instead. */ @Deprecated public interface JsonAvroBinding extends AvroBinding { /** * {@inheritDoc} *

* If necessary, this method automatically performs schema evolution, as * described in {@link AvroCatalog}. In the context of schema evolution, * the writer schema is the one associated internally with the {@code * 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 {@code * value} parameter to conform to the schema of the {@link JsonRecord} that * is returned. * * @return the deserialized {@link JsonRecord} instance. The {@link * JsonRecord#getSchema} method will return the reader schema, which is the * schema that was specified when this binding was created. */ @Override public JsonRecord toObject(Value value) throws SchemaNotAllowedException, IllegalArgumentException; /** * {@inheritDoc} *

* In the context of schema evolution, as described in {@link AvroCatalog}, * the returned value is serialized according to the writer schema. The * writer schema is the one associated with the {@link JsonRecord} * {@code object} parameter; it is returned by {@link JsonRecord#getSchema} * and specified when creating a {@link 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 {@link JsonRecord}. * * @param object the {@link JsonRecord} instance the user wishes to * store, or at least serialize. */ @Override public Value toValue(JsonRecord object) throws SchemaNotAllowedException, UndefinedSchemaException, IllegalArgumentException; /** * Deserialization to JsonRecord using RawBinding, BinaryDecoder and * JsonDatumReader used by import utility. The schema needed for * deserialization is provided by the export package. */ JsonRecord toObjectForImport(Value value, Schema schema) throws SchemaNotAllowedException, IllegalArgumentException; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy