parent
2e9887a3cb
commit
001c2c6282
|
@ -43,9 +43,12 @@ import java.math.RoundingMode;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -1227,52 +1230,101 @@ public final class XContentBuilder implements BytesStream, Releasable {
|
||||||
generator.writeEndObject();
|
generator.writeEndObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
interface Writer {
|
||||||
|
void write(XContentGenerator g, Object v) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static Map<Class<?>, Writer> MAP;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<Class<?>, Writer> map = new HashMap<>();
|
||||||
|
map.put(String.class, (g, v) -> g.writeString((String) v));
|
||||||
|
map.put(Integer.class, (g, v) -> g.writeNumber((Integer) v));
|
||||||
|
map.put(Long.class, (g, v) -> g.writeNumber((Long) v));
|
||||||
|
map.put(Float.class, (g, v) -> g.writeNumber((Float) v));
|
||||||
|
map.put(Double.class, (g, v) -> g.writeNumber((Double) v));
|
||||||
|
map.put(Byte.class, (g, v) -> g.writeNumber((Byte) v));
|
||||||
|
map.put(Short.class, (g, v) -> g.writeNumber((Short) v));
|
||||||
|
map.put(Boolean.class, (g, v) -> g.writeBoolean((Boolean) v));
|
||||||
|
map.put(GeoPoint.class, (g, v) -> {
|
||||||
|
g.writeStartObject();
|
||||||
|
g.writeNumberField("lat", ((GeoPoint) v).lat());
|
||||||
|
g.writeNumberField("lon", ((GeoPoint) v).lon());
|
||||||
|
g.writeEndObject();
|
||||||
|
});
|
||||||
|
map.put(int[].class, (g, v) -> {
|
||||||
|
g.writeStartArray();
|
||||||
|
for (int item : (int[]) v) {
|
||||||
|
g.writeNumber(item);
|
||||||
|
}
|
||||||
|
g.writeEndArray();
|
||||||
|
});
|
||||||
|
map.put(long[].class, (g, v) -> {
|
||||||
|
g.writeStartArray();
|
||||||
|
for (long item : (long[]) v) {
|
||||||
|
g.writeNumber(item);
|
||||||
|
}
|
||||||
|
g.writeEndArray();
|
||||||
|
});
|
||||||
|
map.put(float[].class, (g, v) -> {
|
||||||
|
g.writeStartArray();
|
||||||
|
for (float item : (float[]) v) {
|
||||||
|
g.writeNumber(item);
|
||||||
|
}
|
||||||
|
g.writeEndArray();
|
||||||
|
});
|
||||||
|
map.put(double[].class, (g, v) -> {
|
||||||
|
g.writeStartArray();
|
||||||
|
for (double item : (double[])v) {
|
||||||
|
g.writeNumber(item);
|
||||||
|
}
|
||||||
|
g.writeEndArray();
|
||||||
|
});
|
||||||
|
map.put(byte[].class, (g, v) -> g.writeBinary((byte[]) v));
|
||||||
|
map.put(short[].class, (g, v) -> {
|
||||||
|
g.writeStartArray();
|
||||||
|
for (short item : (short[])v) {
|
||||||
|
g.writeNumber(item);
|
||||||
|
}
|
||||||
|
g.writeEndArray();
|
||||||
|
});
|
||||||
|
map.put(BytesRef.class, (g, v) -> {
|
||||||
|
BytesRef bytes = (BytesRef) v;
|
||||||
|
g.writeBinary(bytes.bytes, bytes.offset, bytes.length);
|
||||||
|
});
|
||||||
|
map.put(Text.class, (g, v) -> {
|
||||||
|
Text text = (Text) v;
|
||||||
|
if (text.hasBytes() && text.bytes().hasArray()) {
|
||||||
|
g.writeUTF8String(text.bytes().array(), text.bytes().arrayOffset(), text.bytes().length());
|
||||||
|
} else if (text.hasString()) {
|
||||||
|
g.writeString(text.string());
|
||||||
|
} else {
|
||||||
|
BytesArray bytesArray = text.bytes().toBytesArray();
|
||||||
|
g.writeUTF8String(bytesArray.array(), bytesArray.arrayOffset(), bytesArray.length());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MAP = Collections.unmodifiableMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
private void writeValue(Object value) throws IOException {
|
private void writeValue(Object value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
generator.writeNull();
|
generator.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Class<?> type = value.getClass();
|
Class<?> type = value.getClass();
|
||||||
if (type == String.class) {
|
Writer writer = MAP.get(type);
|
||||||
generator.writeString((String) value);
|
if (writer != null) {
|
||||||
} else if (type == Integer.class) {
|
writer.write(generator, value);
|
||||||
generator.writeNumber(((Integer) value).intValue());
|
|
||||||
} else if (type == Long.class) {
|
|
||||||
generator.writeNumber(((Long) value).longValue());
|
|
||||||
} else if (type == Float.class) {
|
|
||||||
generator.writeNumber(((Float) value).floatValue());
|
|
||||||
} else if (type == Double.class) {
|
|
||||||
generator.writeNumber(((Double) value).doubleValue());
|
|
||||||
} else if (type == Byte.class) {
|
|
||||||
generator.writeNumber(((Byte)value).byteValue());
|
|
||||||
} else if (type == Short.class) {
|
|
||||||
generator.writeNumber(((Short) value).shortValue());
|
|
||||||
} else if (type == Boolean.class) {
|
|
||||||
generator.writeBoolean(((Boolean) value).booleanValue());
|
|
||||||
} else if (type == GeoPoint.class) {
|
|
||||||
generator.writeStartObject();
|
|
||||||
generator.writeNumberField("lat", ((GeoPoint) value).lat());
|
|
||||||
generator.writeNumberField("lon", ((GeoPoint) value).lon());
|
|
||||||
generator.writeEndObject();
|
|
||||||
} else if (value instanceof Map) {
|
} else if (value instanceof Map) {
|
||||||
writeMap((Map) value);
|
writeMap((Map) value);
|
||||||
} else if (value instanceof Path) {
|
} else if (value instanceof Path) {
|
||||||
//Path implements Iterable<Path> and causes endless recursion and a StackOverFlow if treated as an Iterable here
|
//Path implements Iterable<Path> and causes endless recursion and a StackOverFlow if treated as an Iterable here
|
||||||
generator.writeString(value.toString());
|
generator.writeString(value.toString());
|
||||||
} else if (value instanceof Iterable) {
|
} else if (value instanceof Iterable) {
|
||||||
generator.writeStartArray();
|
writeIterable((Iterable<?>) value);
|
||||||
for (Object v : (Iterable<?>) value) {
|
|
||||||
writeValue(v);
|
|
||||||
}
|
|
||||||
generator.writeEndArray();
|
|
||||||
} else if (value instanceof Object[]) {
|
} else if (value instanceof Object[]) {
|
||||||
generator.writeStartArray();
|
writeObjectArray((Object[]) value);
|
||||||
for (Object v : (Object[]) value) {
|
|
||||||
writeValue(v);
|
|
||||||
}
|
|
||||||
generator.writeEndArray();
|
|
||||||
} else if (type == byte[].class) {
|
|
||||||
generator.writeBinary((byte[]) value);
|
|
||||||
} else if (value instanceof Date) {
|
} else if (value instanceof Date) {
|
||||||
generator.writeString(XContentBuilder.defaultDatePrinter.print(((Date) value).getTime()));
|
generator.writeString(XContentBuilder.defaultDatePrinter.print(((Date) value).getTime()));
|
||||||
} else if (value instanceof Calendar) {
|
} else if (value instanceof Calendar) {
|
||||||
|
@ -1280,56 +1332,9 @@ public final class XContentBuilder implements BytesStream, Releasable {
|
||||||
} else if (value instanceof ReadableInstant) {
|
} else if (value instanceof ReadableInstant) {
|
||||||
generator.writeString(XContentBuilder.defaultDatePrinter.print((((ReadableInstant) value)).getMillis()));
|
generator.writeString(XContentBuilder.defaultDatePrinter.print((((ReadableInstant) value)).getMillis()));
|
||||||
} else if (value instanceof BytesReference) {
|
} else if (value instanceof BytesReference) {
|
||||||
BytesReference bytes = (BytesReference) value;
|
writeBytesReference((BytesReference) value);
|
||||||
if (!bytes.hasArray()) {
|
|
||||||
bytes = bytes.toBytesArray();
|
|
||||||
}
|
|
||||||
generator.writeBinary(bytes.array(), bytes.arrayOffset(), bytes.length());
|
|
||||||
} else if (value instanceof BytesRef) {
|
|
||||||
BytesRef bytes = (BytesRef) value;
|
|
||||||
generator.writeBinary(bytes.bytes, bytes.offset, bytes.length);
|
|
||||||
} else if (value instanceof Text) {
|
|
||||||
Text text = (Text) value;
|
|
||||||
if (text.hasBytes() && text.bytes().hasArray()) {
|
|
||||||
generator.writeUTF8String(text.bytes().array(), text.bytes().arrayOffset(), text.bytes().length());
|
|
||||||
} else if (text.hasString()) {
|
|
||||||
generator.writeString(text.string());
|
|
||||||
} else {
|
|
||||||
BytesArray bytesArray = text.bytes().toBytesArray();
|
|
||||||
generator.writeUTF8String(bytesArray.array(), bytesArray.arrayOffset(), bytesArray.length());
|
|
||||||
}
|
|
||||||
} else if (value instanceof ToXContent) {
|
} else if (value instanceof ToXContent) {
|
||||||
((ToXContent) value).toXContent(this, ToXContent.EMPTY_PARAMS);
|
((ToXContent) value).toXContent(this, ToXContent.EMPTY_PARAMS);
|
||||||
} else if (value instanceof double[]) {
|
|
||||||
generator.writeStartArray();
|
|
||||||
for (double v : (double[]) value) {
|
|
||||||
generator.writeNumber(v);
|
|
||||||
}
|
|
||||||
generator.writeEndArray();
|
|
||||||
} else if (value instanceof long[]) {
|
|
||||||
generator.writeStartArray();
|
|
||||||
for (long v : (long[]) value) {
|
|
||||||
generator.writeNumber(v);
|
|
||||||
}
|
|
||||||
generator.writeEndArray();
|
|
||||||
} else if (value instanceof int[]) {
|
|
||||||
generator.writeStartArray();
|
|
||||||
for (int v : (int[]) value) {
|
|
||||||
generator.writeNumber(v);
|
|
||||||
}
|
|
||||||
generator.writeEndArray();
|
|
||||||
} else if (value instanceof float[]) {
|
|
||||||
generator.writeStartArray();
|
|
||||||
for (float v : (float[]) value) {
|
|
||||||
generator.writeNumber(v);
|
|
||||||
}
|
|
||||||
generator.writeEndArray();
|
|
||||||
} else if (value instanceof short[]) {
|
|
||||||
generator.writeStartArray();
|
|
||||||
for (short v : (short[]) value) {
|
|
||||||
generator.writeNumber(v);
|
|
||||||
}
|
|
||||||
generator.writeEndArray();
|
|
||||||
} else {
|
} else {
|
||||||
// if this is a "value" object, like enum, DistanceUnit, ..., just toString it
|
// if this is a "value" object, like enum, DistanceUnit, ..., just toString it
|
||||||
// yea, it can be misleading when toString a Java class, but really, jackson should be used in that case
|
// yea, it can be misleading when toString a Java class, but really, jackson should be used in that case
|
||||||
|
@ -1337,4 +1342,29 @@ public final class XContentBuilder implements BytesStream, Releasable {
|
||||||
//throw new ElasticsearchIllegalArgumentException("type not supported for generic value conversion: " + type);
|
//throw new ElasticsearchIllegalArgumentException("type not supported for generic value conversion: " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeBytesReference(BytesReference value) throws IOException {
|
||||||
|
BytesReference bytes = value;
|
||||||
|
if (!bytes.hasArray()) {
|
||||||
|
bytes = bytes.toBytesArray();
|
||||||
|
}
|
||||||
|
generator.writeBinary(bytes.array(), bytes.arrayOffset(), bytes.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeIterable(Iterable<?> value) throws IOException {
|
||||||
|
generator.writeStartArray();
|
||||||
|
for (Object v : value) {
|
||||||
|
writeValue(v);
|
||||||
|
}
|
||||||
|
generator.writeEndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeObjectArray(Object[] value) throws IOException {
|
||||||
|
generator.writeStartArray();
|
||||||
|
for (Object v : value) {
|
||||||
|
writeValue(v);
|
||||||
|
}
|
||||||
|
generator.writeEndArray();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue