net.cadrian.jsonref.SerializationProcessor Maven / Gradle / Ivy
The newest version!
/*
Copyright 2015 Cyril Adrian
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net.cadrian.jsonref;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.cadrian.jsonref.Prettiness.Context;
import net.cadrian.jsonref.data.AbstractSerializationObject;
import net.cadrian.jsonref.data.SerializationArray;
import net.cadrian.jsonref.data.SerializationHeap;
import net.cadrian.jsonref.data.SerializationMap;
import net.cadrian.jsonref.data.SerializationObject;
import net.cadrian.jsonref.data.SerializationRef;
import net.cadrian.jsonref.data.SerializationValue;
/**
* Handle JSON/R serialization in two steps: build the intermediate
* {@link SerializationData} tree, the build the JSON/R string from that
*/
class SerializationProcessor {
private static class ObjectReference {
private final Object object;
private final int id;
/**
* @param object
* @param generator
*/
public ObjectReference(final Object object, final int id) {
this.object = object;
this.id = id;
}
/**
* Getter object
*
* @return the object
*/
public Object getObject() {
return object;
}
/**
* Getter id
*
* @return the id
*/
public int getId() {
return id;
}
/**
* {@inheritDoc}
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
boolean result = false;
if (obj instanceof ObjectReference) {
result = object == ((ObjectReference) obj).object;
}
return result;
}
/**
* {@inheritDoc}
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return object.hashCode();
}
}
/**
* Serialize an object graph to JSON/R
*
* @param value
* the object to serialize
* @param converter
* the converter
* @param context
* the prettiness level
* @return the serialized object
*/
public String serialize(final Object value, final JsonConverter converter,
final Context context) {
final StringBuilderWriter result = new StringBuilderWriter();
try {
serializeTo(value, result, converter, context);
} catch (final IOException e) {
// should not happen anyway
throw new RuntimeException(e);
}
return result.toString();
}
/**
* Serialize an object graph to JSON/R
*
* @param value
* the object to serialize
* @param out
* the stream to write to
* @param converter
* the converter
* @param context
* the prettiness level
* @return the serialized object
* @throws IOException
* on exception
*/
public void serializeTo(final Object value, final Writer out,
final JsonConverter converter, Context context) throws IOException {
if (value == null) {
out.write("null");
} else {
if (context == null) {
context = Prettiness.COMPACT.newContext();
}
final JsonConverter.Context converterContext = converter
.getNewContext();
final Map refs = new HashMap<>();
final SerializationData data = getData(null, refs, value,
value.getClass(), converter, converterContext);
if (data != null) {
data.toJson(out, converter, context);
} else {
final SerializationHeap heap = new SerializationHeap();
getData(heap, refs, value, value.getClass(), converter,
converterContext);
heap.toJson(out, converter, context);
}
}
}
private SerializationData getData(final SerializationHeap heap,
final Map refs,
final Object value, final Class> propertyType,
final JsonConverter converter,
final JsonConverter.Context converterContext) {
final SerializationData data;
if (value == null) {
data = new SerializationValue(propertyType, null);
} else if (converter.isAtomicValue(value.getClass())) {
data = new SerializationValue(value.getClass(), value);
} else if (propertyType == Class.class) {
data = new SerializationValue(propertyType,
((Class>) value).getName());
} else if (heap != null) {
data = getHeapData(value, propertyType, heap, refs, converter,
converterContext);
} else {
data = null;
}
return data;
}
private SerializationData getHeapData(final Object value,
final Class> propertyType, final SerializationHeap heap,
final Map refs,
final JsonConverter converter,
final JsonConverter.Context converterContext) {
final SerializationData result;
final ObjectReference ref = refs.get(new ObjectReference(value, 0));
if (ref != null) {
result = new SerializationRef(ref.getId());
} else if (propertyType.isArray()) {
result = serializeArray(new ObjectReference(value, heap.nextRef()),
propertyType, heap, refs, converter, converterContext);
} else if (Collection.class.isAssignableFrom(propertyType)) {
result = serializeCollection(
new ObjectReference(value, heap.nextRef()), propertyType,
heap, refs, converter, converterContext);
} else if (Map.class.isAssignableFrom(propertyType)) {
result = serializeMap(new ObjectReference(value, heap.nextRef()),
propertyType, heap, refs, converter, converterContext);
} else {
final int objectId = serializeObject(new ObjectReference(value,
heap.nextRef()), heap, refs, converter, converterContext);
result = new SerializationRef(objectId);
}
return result;
}
private SerializationArray serializeArray(final ObjectReference ref,
final Class> propertyType, final SerializationHeap heap,
final Map refs,
final JsonConverter converter,
final JsonConverter.Context converterContext) {
final Object array = ref.getObject();
final int n = Array.getLength(array);
final Class> componentType = propertyType.getComponentType();
final SerializationArray result = new SerializationArray(n,
propertyType, ref.getId());
heap.add(result);
refs.put(ref, ref);
for (int i = 0; i < n; i++) {
result.add(getData(heap, refs, Array.get(array, i), componentType,
converter, converterContext));
}
return result;
}
private SerializationArray serializeCollection(final ObjectReference ref,
final Class> propertyType, final SerializationHeap heap,
final Map refs,
final JsonConverter converter,
final JsonConverter.Context converterContext) {
@SuppressWarnings("unchecked")
final Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy