blob: 9ad21a83cf88c7956c808857b407d85bfe52923e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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 org.apache.geode.pdx.internal.json;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import org.apache.geode.annotations.internal.MutableForTesting;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.pdx.PdxInstance;
import org.apache.geode.pdx.internal.EnumInfo;
import org.apache.geode.pdx.internal.EnumInfo.PdxInstanceEnumInfo;
/*
* This class converts a PdxInstance into a JSON document.
*/
public class PdxToJSON {
@MutableForTesting
public static boolean PDXTOJJSON_UNQUOTEFIELDNAMES =
Boolean.getBoolean("pdxToJson.unQuoteFieldNames");
private PdxInstance m_pdxInstance;
public PdxToJSON(PdxInstance pdx) {
m_pdxInstance = pdx;
}
public String getJSON() {
JsonFactory jf = new JsonFactory();
HeapDataOutputStream hdos = new HeapDataOutputStream(org.apache.geode.internal.Version.CURRENT);
try {
JsonGenerator jg = jf.createJsonGenerator(hdos, JsonEncoding.UTF8);
enableDisableJSONGeneratorFeature(jg);
getJSONString(jg, m_pdxInstance);
jg.close();
return new String(hdos.toByteArray());
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
} finally {
hdos.close();
}
}
public byte[] getJSONByteArray() {
JsonFactory jf = new JsonFactory();
HeapDataOutputStream hdos = new HeapDataOutputStream(org.apache.geode.internal.Version.CURRENT);
try {
JsonGenerator jg = jf.createJsonGenerator(hdos, JsonEncoding.UTF8);
enableDisableJSONGeneratorFeature(jg);
getJSONString(jg, m_pdxInstance);
jg.close();
return hdos.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
} finally {
hdos.close();
}
}
private void enableDisableJSONGeneratorFeature(JsonGenerator jg) {
jg.enable(Feature.ESCAPE_NON_ASCII);
jg.disable(Feature.AUTO_CLOSE_TARGET);
if (PDXTOJJSON_UNQUOTEFIELDNAMES)
jg.disable(Feature.QUOTE_FIELD_NAMES);
}
protected String convertPdxToJson(final PdxInstance pdxObj) {
return (pdxObj != null ? JSONFormatter.toJSON(pdxObj) : null);
}
private void writeValue(JsonGenerator jg, Object value, String pf)
throws JsonGenerationException, IOException {
if (value == null) {
jg.writeNull();
} else if (value.getClass().equals(Boolean.class)) {
boolean b = (Boolean) value;
jg.writeBoolean(b);
} else if (value.getClass().equals(Byte.class)) {
Byte b = (Byte) value;
jg.writeNumber(b);
} else if (value.getClass().equals(Short.class)) {
Short b = (Short) value;
jg.writeNumber(b);
} else if (value.getClass().equals(Integer.class)) {
int i = (Integer) value;
jg.writeNumber(i);
} else if (value.getClass().equals(Long.class)) {
long i = (Long) value;
jg.writeNumber(i);
} else if (value.getClass().equals(BigInteger.class)) {
BigInteger i = (BigInteger) value;
jg.writeNumber(i);
} else if (value.getClass().equals(Float.class)) {
float i = (Float) value;
jg.writeNumber(i);
} else if (value.getClass().equals(BigDecimal.class)) {
BigDecimal i = (BigDecimal) value;
jg.writeNumber(i);
} else if (value.getClass().equals(Double.class)) {
double d = (Double) value;
jg.writeNumber(d);
} else if (value.getClass().equals(String.class)) {
String s = (String) value;
jg.writeString(s);
} else if (value.getClass().isArray()) {
getJSONStringFromArray(jg, value, pf);
} else if (value.getClass().equals(EnumInfo.class)) {
jg.writeString(value.toString());
} else if (value.getClass().equals(PdxInstanceEnumInfo.class)) {
jg.writeString(value.toString());
} else {
if (value instanceof PdxInstance) {
getJSONString(jg, (PdxInstance) value);
} else if (value instanceof Collection) {
getJSONStringFromCollection(jg, (Collection<?>) value, pf);
} else if (value instanceof Map) {
getJSONStringFromMap(jg, (Map) value, pf);
} else {
throw new IllegalStateException(
"PdxInstance returns unknwon pdxfield " + pf + " for type " + value);
}
}
}
private void getJSONStringFromMap(JsonGenerator jg, Map map, String pf)
throws JsonGenerationException, IOException {
jg.writeStartObject();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
// Iterate over Map and write key-value
jg.writeFieldName(entry.getKey().toString()); // write Key in a Map
writeValue(jg, entry.getValue(), pf); // write value in a Map
}
jg.writeEndObject();
}
private String getJSONString(JsonGenerator jg, PdxInstance pdxInstance)
throws JsonGenerationException, IOException {
jg.writeStartObject();
List<String> pdxFields = pdxInstance.getFieldNames();
for (String pf : pdxFields) {
Object value = pdxInstance.getField(pf);
jg.writeFieldName(pf);
writeValue(jg, value, pf);
}
jg.writeEndObject();
return null;
}
private void getJSONStringFromArray(JsonGenerator jg, Object value, String pf)
throws JsonGenerationException, IOException {
if (value.getClass().getName().equals("[Z")) {
JsonHelper.getJsonFromPrimitiveBoolArray(jg, (boolean[]) value, pf);
} else if (value.getClass().getName().equals("[B")) {
JsonHelper.getJsonFromPrimitiveByteArray(jg, (byte[]) value, pf);
} else if (value.getClass().getName().equals("[S")) {
JsonHelper.getJsonFromPrimitiveShortArray(jg, (short[]) value, pf);
} else if (value.getClass().getName().equals("[I")) {
JsonHelper.getJsonFromPrimitiveIntArray(jg, (int[]) value, pf);
} else if (value.getClass().getName().equals("[J")) {
JsonHelper.getJsonFromPrimitiveLongArray(jg, (long[]) value, pf);
} else if (value.getClass().getName().equals("[F")) {
JsonHelper.getJsonFromPrimitiveFloatArray(jg, (float[]) value, pf);
} else if (value.getClass().getName().equals("[D")) {
JsonHelper.getJsonFromPrimitiveDoubleArray(jg, (double[]) value, pf);
} else if (value.getClass().equals(Boolean[].class)) {
JsonHelper.getJsonFromWrapperBoolArray(jg, (Boolean[]) value, pf);
} else if (value.getClass().equals(Byte[].class)) {
JsonHelper.getJsonFromWrapperByteArray(jg, (Byte[]) value, pf);
} else if (value.getClass().equals(Short[].class)) {
JsonHelper.getJsonFromWrapperShortArray(jg, (Short[]) value, pf);
} else if (value.getClass().equals(Integer[].class)) {
JsonHelper.getJsonFromWrapperIntArray(jg, (Integer[]) value, pf);
} else if (value.getClass().equals(Long[].class)) {
JsonHelper.getJsonFromWrapperLongArray(jg, (Long[]) value, pf);
} else if (value.getClass().equals(Float[].class)) {
JsonHelper.getJsonFromWrapperFloatArray(jg, (Float[]) value, pf);
} else if (value.getClass().equals(Double[].class)) {
JsonHelper.getJsonFromWrapperDoubleArray(jg, (Double[]) value, pf);
} else if (value.getClass().equals(BigInteger[].class)) {
JsonHelper.getJsonFromBigIntArray(jg, (BigInteger[]) value, pf);
} else if (value.getClass().equals(BigDecimal[].class)) {
JsonHelper.getJsonFromBigDecimalArray(jg, (BigDecimal[]) value, pf);
} else if (value.getClass().equals(String[].class)) {
JsonHelper.getJsonFromStringArray(jg, (String[]) value, pf);
} else if (value.getClass().equals(Object[].class)) {
jg.writeStartArray();
Object[] array = (Object[]) value;
for (Object obj : array) {
writeValue(jg, obj, pf);
}
jg.writeEndArray();
} else {
throw new IllegalStateException(
"PdxInstance returns unknown pdxfield " + pf + " for type " + value);
}
}
private void getJSONStringFromCollection(JsonGenerator jg, Collection<?> coll, String pf)
throws JsonGenerationException, IOException {
jg.writeStartArray();
for (Object obj : coll) {
writeValue(jg, obj, pf);
}
jg.writeEndArray();
}
}