Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.caucho.v5.json.ser.JavaSerializerJson Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2015 Caucho Technology -- all rights reserved
*
* This file is part of Baratine(TM)
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Baratine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Baratine 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Baratine; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.v5.json.ser;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.caucho.v5.convert.bean.FieldBase;
import com.caucho.v5.convert.bean.FieldBoolean;
import com.caucho.v5.convert.bean.FieldByte;
import com.caucho.v5.convert.bean.FieldChar;
import com.caucho.v5.convert.bean.FieldDouble;
import com.caucho.v5.convert.bean.FieldFloat;
import com.caucho.v5.convert.bean.FieldInt;
import com.caucho.v5.convert.bean.FieldLong;
import com.caucho.v5.convert.bean.FieldObject;
import com.caucho.v5.convert.bean.FieldShort;
import com.caucho.v5.convert.bean.FieldString;
import com.caucho.v5.inject.type.TypeRef;
import com.caucho.v5.json.JsonName;
import com.caucho.v5.json.JsonTransient;
import com.caucho.v5.json.io.InJson.Event;
import com.caucho.v5.json.io.JsonReader;
import com.caucho.v5.json.io.JsonWriter;
public class JavaSerializerJson extends JsonObjectSerializerBase
{
private static final Logger log
= Logger.getLogger(JavaSerializerJson.class.getName());
private static final HashMap,BiFunction>>
_fieldFunMap;
private TypeRef _type;
private JsonField []_fields;
private HashMap> _fieldMap
= new HashMap<>();
private Constructor> _ctor;
JavaSerializerJson(TypeRef type,
JsonFactory factory)
{
_type = type;
introspect(factory);
}
@Override
public JavaSerializerJson withType(TypeRef typeRef, JsonFactory factory)
{
if (typeRef.equals(_type)) {
return this;
}
return new JavaSerializerJson<>(typeRef, factory);
}
void introspect(JsonFactory factory)
{
try {
_ctor = introspectConstructor(_type);
_ctor.setAccessible(true);
//introspectFields(_type, factory);
ArrayList> fields = new ArrayList<>();
introspectFields(fields, _type, factory);
Collections.sort(fields, (x,y)->x.name().compareTo(y.name()));
_fields = new JsonField[fields.size()];
fields.toArray(_fields);
for (JsonField field : _fields) {
_fieldMap.put(field.name(), field);
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new JsonException(e);
}
}
private void introspectFields(ArrayList> fields,
TypeRef typeRef,
JsonFactory factory)
{
if (typeRef == null) {
return;
}
introspectFields(fields, typeRef.superClass(), factory);
for (Field field : typeRef.rawClass().getDeclaredFields()) {
if (Modifier.isTransient(field.getModifiers())) {
continue;
}
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (field.getAnnotation(JsonTransient.class) != null) {
continue;
}
field.setAccessible(true);
String name = field.getName();
JsonName json = field.getAnnotation(JsonName.class);
if (json != null) {
name = json.value();
}
BiFunction> fieldFun;
fieldFun = _fieldFunMap.get(field.getType());
JsonField jsonField;
if (fieldFun != null) {
jsonField = (JsonField) fieldFun.apply(field, name);
}
/*
else if (Modifier.isFinal(field.getType().getModifiers())) {
JsonSerializer> ser = factory.serializer(field.getType());
jsonField = new JsonFieldFinal(field, json, ser);
}
*/
else {
//TypeRef type = _type.child(field.getGenericType());
TypeRef type = typeRef.child(field.getGenericType());
SerializerJson> ser = factory.serializer(type);
jsonField = new JsonFieldObject<>(field, name, ser);
}
fields.add(jsonField);
}
}
@Override
public void write(JsonWriter out, Object value)
{
out.writeStartObject();
writeFields(out, value);
out.writeEndObject();
}
/*
@Override
public void write(JsonWriter out,
String name,
Object value)
{
out.writeStartObject(name);
writeFields(out, value);
out.writeEnd();
}
*/
private void writeFields(JsonWriter out, Object value)
{
for (JsonField field : _fields) {
field.write(out, value);
}
}
private Constructor> introspectConstructor(TypeRef type)
{
for (Constructor> ctor : type.rawClass().getDeclaredConstructors()) {
if (ctor.getParameterTypes().length == 0)
return ctor;
}
if (type.rawClass().isInterface()) {
throw new JsonException(type + " cannot be deserialized because it is an interface."
+ " JSON deserialization requires concrete types.");
}
else if (Modifier.isAbstract(type.rawClass().getModifiers())) {
throw new JsonException(type + " cannot be deserialized because it is abstract."
+ " JSON deserialization requires concrete types.");
}
throw new IllegalStateException(type + " cannot be deserialized because it does not have a zero-arg constructor."
+ " JSON deserialization requires zero-arg constructors.");
}
@Override
public Object read(JsonReader in)
{
Event event = in.next();
if (event == null) {
return null;
}
switch (event) {
case VALUE_NULL:
return null;
case START_OBJECT:
{
Object bean = create();
in.parseBeanMap(bean, this);
return bean;
}
default:
throw error("unexpected token: {0} while parsing {1}",
event, _type.rawClass());
}
}
public Object create()
{
try {
return _ctor.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void readField(JsonReader in, Object bean, String fieldName)
{
JsonField jsonField = _fieldMap.get(fieldName);
if (jsonField != null) {
jsonField.read(in, bean);
}
else {
// skip
try {
in.readObject();
} catch (Exception e) {
log.log(Level.FINER, e.toString(), e);
}
}
}
public Object complete(Object bean)
{
return bean;
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + _type + "]";
}
abstract static class JsonField
{
private final Field _field;
private final String _name;
private final char []_key;
JsonField(Field field, String name)
{
_field = field;
Objects.requireNonNull(name);
_name = name;
_key = ("\"" + _name + "\":").toCharArray();
}
public final Field field()
{
return _field;
}
public final String name()
{
return _name;
}
public final char []key()
{
return _key;
}
//abstract V get(T bean);
abstract void write(JsonWriter out, T bean);
void read(JsonReader in, T bean)
{
throw new UnsupportedOperationException(getClass().getName());
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + _name + "]";
}
}
/**
* String field
*/
static final class JsonFieldString extends JsonField
{
private final FieldString _fieldRef;
JsonFieldString(Field field, String name)
{
super(field, name);
_fieldRef = new FieldString<>(field);
}
/*
@Override
public final String get(T bean)
{
return _fieldRef.getString(bean);
}
*/
@Override
final void write(JsonWriter out, T bean)
{
String fieldValue = _fieldRef.getString(bean);
if (fieldValue != null) {
out.writeKey(key());
out.write(fieldValue);
}
}
@Override
void read(JsonReader in, T bean)
{
String value = in.readString();
_fieldRef.setString(bean, value);
}
}
/**
* boolean field
*/
static class JsonFieldBoolean extends JsonField
{
private final FieldBoolean _fieldRef;
JsonFieldBoolean(Field field, String name)
{
super(field, name);
_fieldRef = new FieldBoolean<>(field);
}
/*
@Override
public final Boolean get(T bean)
{
return _fieldRef.getBoolean(bean);
}
*/
@Override
final void write(JsonWriter out, T bean)
{
boolean fieldValue = _fieldRef.getBoolean(bean);
out.writeKey(key());
out.write(fieldValue);
}
@Override
void read(JsonReader in, T bean)
{
_fieldRef.setBoolean(bean, in.readBoolean());
}
}
static class JsonFieldChar extends JsonField
{
private final FieldChar _fieldRef;
JsonFieldChar(Field field, String name)
{
super(field, name);
_fieldRef = new FieldChar<>(field);
}
/*
@Override
public final Character get(T bean)
{
return (char) _fieldRef.getInt(bean);
}
*/
@Override
final void write(JsonWriter out, T bean)
{
String fieldValue = _fieldRef.getString(bean);
out.writeKey(key());
out.write(fieldValue);
}
@Override
void read(JsonReader in, T bean)
{
try {
String v = in.readString();
char ch;
if (v == null || v.equals("")) {
ch = 0;
}
else {
ch = v.charAt(0);
}
_fieldRef.setChar(bean, ch);
} catch (Exception e) {
throw new JsonException(field().getName() + ": " + e, e);
}
}
}
static class JsonFieldLong extends JsonField
{
private final FieldBase _fieldRef;
JsonFieldLong(Field field, String name)
{
super(field, name);
Class> fieldType = field.getType();
if (byte.class.equals(fieldType)) {
_fieldRef = new FieldByte<>(field);
}
else if (short.class.equals(fieldType)) {
_fieldRef = new FieldShort<>(field);
}
else if (int.class.equals(fieldType)) {
_fieldRef = new FieldInt<>(field);
}
else if (int.class.equals(fieldType)) {
_fieldRef = new FieldLong<>(field);
}
else {
throw new UnsupportedOperationException(fieldType.getName());
}
}
/*
@Override
public final Long get(T bean)
{
return _fieldRef.getLong(bean);
}
*/
@Override
final void write(JsonWriter out, T bean)
{
long fieldValue = _fieldRef.getLong(bean);
out.writeKey(key());
out.write(fieldValue);
}
@Override
void read(JsonReader in, T bean)
{
_fieldRef.setLong(bean, in.readLong());
}
}
static class JsonFieldDouble extends JsonField
{
private final FieldBase _fieldRef;
JsonFieldDouble(Field field, String name)
{
super(field, name);
Class> fieldType = field.getType();
if (float.class.equals(fieldType)) {
_fieldRef = new FieldFloat<>(field);
}
else if (double.class.equals(fieldType)) {
_fieldRef = new FieldDouble<>(field);
}
else {
throw new UnsupportedOperationException(fieldType.getName());
}
}
/*
@Override
public final Double get(T bean)
{
return _fieldRef.getDouble(bean);
}
*/
@Override
final void write(JsonWriter out, T bean)
{
double fieldValue = _fieldRef.getDouble(bean);
out.writeKey(key());
out.write(fieldValue);
}
@Override
void read(JsonReader in, T bean)
{
_fieldRef.setDouble(bean, in.readDouble());
}
}
static class JsonFieldObject extends JsonField
{
private final FieldObject _fieldRef;
private final SerializerJson _ser;
JsonFieldObject(Field field,
String name,
SerializerJson ser)
{
super(field, name);
_fieldRef = new FieldObject<>(field);
Objects.requireNonNull(ser);
_ser = ser;
}
@Override
void read(JsonReader in, T bean)
{
V value = _ser.read(in);
_fieldRef.setObject(bean, value);
}
@Override
void write(JsonWriter out, T bean)
{
V fieldValue = _fieldRef.getObject(bean);
if (fieldValue == null) {
return;
}
out.writeKey(key());
// XXX: type check
if (_ser.rawClass() == fieldValue.getClass()) {
_ser.write(out, fieldValue);
}
else {
out.write(fieldValue);
}
}
}
static {
_fieldFunMap = new HashMap<>();
_fieldFunMap.put(boolean.class, JsonFieldBoolean::new);
_fieldFunMap.put(char.class, JsonFieldChar::new);
_fieldFunMap.put(byte.class, JsonFieldLong::new);
_fieldFunMap.put(short.class, JsonFieldLong::new);
_fieldFunMap.put(int.class, JsonFieldLong::new);
_fieldFunMap.put(float.class, JsonFieldDouble::new);
_fieldFunMap.put(double.class, JsonFieldDouble::new);
_fieldFunMap.put(String.class, JsonFieldString::new);
}
}