package com.fasterxml.jackson.datatype.jsr353;
import java.io.IOException;
import javax.json.*;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonParser.NumberType;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.type.LogicalType;
import com.fasterxml.jackson.databind.util.ClassUtil;
public class JsonValueDeserializer extends StdDeserializer<JsonValue> {
private static final long serialVersionUID = 1L;
protected final JsonBuilderFactory _builderFactory;
protected final boolean _forJsonValue;
@Deprecated
public JsonValueDeserializer(JsonBuilderFactory bf) {
this(JsonValue.class, bf);
}
public JsonValueDeserializer(Class<?> target, JsonBuilderFactory bf) {
super(target);
_builderFactory = bf;
_forJsonValue = (target == JsonValue.class);
}
@Override
public LogicalType logicalType() {
return LogicalType.Untyped;
}
@Override
public JsonValue deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException
{
JsonValue v;
switch (p.getCurrentToken()) {
case START_OBJECT:
v = _deserializeObject(p, ctxt);
break;
case START_ARRAY:
v = _deserializeArray(p, ctxt);
break;
default:
v = _deserializeScalar(p, ctxt);
}
if (!_forJsonValue) {
if (!handledType().isAssignableFrom(v.getClass())) {
ctxt.reportInputMismatch(handledType(),
"Expected %s, but encountered %s Value",
ClassUtil.getClassDescription(handledType()),
v.getValueType().toString()
);
}
}
return v;
}
@Override
public JsonValue getNullValue(final DeserializationContext ctxt) {
if (_forJsonValue) {
return JsonValue.NULL;
}
return null;
}
@Override
public Object deserializeWithType(JsonParser p,
DeserializationContext ctxt, TypeDeserializer typeDeser)
throws IOException
{
return typeDeser.deserializeTypedFromScalar(p, ctxt);
}
protected JsonObject _deserializeObject(JsonParser p, DeserializationContext ctxt)
throws IOException
{
JsonObjectBuilder b = _builderFactory.createObjectBuilder();
while (p.nextToken() != JsonToken.END_OBJECT) {
String name = p.getCurrentName();
JsonToken t = p.nextToken();
switch (t) {
case START_ARRAY:
b.add(name, _deserializeArray(p, ctxt));
break;
case START_OBJECT:
b.add(name, _deserializeObject(p, ctxt));
break;
case VALUE_FALSE:
b.add(name, false);
break;
case VALUE_TRUE:
b.add(name, true);
break;
case VALUE_NULL:
b.addNull(name);
break;
case VALUE_NUMBER_FLOAT:
if (p.getNumberType() == NumberType.BIG_DECIMAL) {
b.add(name, p.getDecimalValue());
} else {
b.add(name, p.getDoubleValue());
}
break;
case VALUE_NUMBER_INT:
switch (p.getNumberType()) {
case LONG:
b.add(name, p.getLongValue());
break;
case INT:
b.add(name, p.getIntValue());
break;
default:
b.add(name, p.getBigIntegerValue());
}
break;
case VALUE_STRING:
b.add(name, p.getText());
break;
case VALUE_EMBEDDED_OBJECT: {
Object ob = p.getEmbeddedObject();
if (ob instanceof byte[]) {
String b64 = ctxt.getBase64Variant().encode((byte[]) ob, false);
b.add(name, b64);
break;
}
}
default:
return (JsonObject) ctxt.handleUnexpectedToken(JsonObject.class, p);
}
}
return b.build();
}
protected JsonArray _deserializeArray(JsonParser p, DeserializationContext ctxt)
throws IOException
{
JsonArrayBuilder b = _builderFactory.createArrayBuilder();
JsonToken t;
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
switch (t) {
case START_ARRAY:
b.add(_deserializeArray(p, ctxt));
break;
case START_OBJECT:
b.add(_deserializeObject(p, ctxt));
break;
case VALUE_FALSE:
b.add(false);
break;
case VALUE_TRUE:
b.add(true);
break;
case VALUE_NULL:
b.addNull();
break;
case VALUE_NUMBER_FLOAT:
if (p.getNumberType() == NumberType.BIG_DECIMAL) {
b.add(p.getDecimalValue());
} else {
b.add(p.getDoubleValue());
}
break;
case VALUE_NUMBER_INT:
switch (p.getNumberType()) {
case LONG:
b.add(p.getLongValue());
break;
case INT:
b.add(p.getIntValue());
break;
default:
b.add(p.getBigIntegerValue());
}
break;
case VALUE_STRING:
b.add(p.getText());
break;
default:
return (JsonArray) ctxt.handleUnexpectedToken(JsonArray.class, p);
}
}
return b.build();
}
protected JsonValue _deserializeScalar(JsonParser p, DeserializationContext ctxt)
throws IOException
{
switch (p.getCurrentToken()) {
case VALUE_EMBEDDED_OBJECT:
return (JsonValue) ctxt.handleUnexpectedToken(JsonValue.class, p);
case VALUE_FALSE:
return JsonValue.FALSE;
case VALUE_TRUE:
return JsonValue.TRUE;
case VALUE_NULL:
return JsonValue.NULL;
case VALUE_NUMBER_FLOAT:
{
JsonArrayBuilder b = _builderFactory.createArrayBuilder();
if (p.getNumberType() == NumberType.BIG_DECIMAL) {
return b.add(p.getDecimalValue()).build().get(0);
}
return b.add(p.getDoubleValue()).build().get(0);
}
case VALUE_NUMBER_INT:
{
JsonArrayBuilder b = _builderFactory.createArrayBuilder();
switch (p.getNumberType()) {
case LONG:
return b.add(p.getLongValue()).build().get(0);
case INT:
return b.add(p.getIntValue()).build().get(0);
default:
return b.add(p.getBigIntegerValue()).build().get(0);
}
}
case VALUE_STRING:
return _builderFactory.createArrayBuilder().add(p.getText()).build().get(0);
default:
return (JsonValue) ctxt.handleUnexpectedToken(JsonValue.class, p);
}
}
}