co.elastic.clients.json.JsonpDeserializerBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch-java Show documentation
Show all versions of elasticsearch-java Show documentation
Elasticsearch Java API Client
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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 co.elastic.clients.json;
import jakarta.json.JsonNumber;
import jakarta.json.JsonValue;
import jakarta.json.stream.JsonParser;
import jakarta.json.stream.JsonParser.Event;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Base class for {@link JsonpDeserializer} implementations that accept a set of JSON events known at instanciation time.
*/
public abstract class JsonpDeserializerBase implements JsonpDeserializer {
private final EnumSet acceptedEvents;
private final EnumSet nativeEvents;
protected JsonpDeserializerBase(EnumSet acceptedEvents) {
this(acceptedEvents, acceptedEvents);
}
protected JsonpDeserializerBase(EnumSet acceptedEvents, EnumSet nativeEvents) {
this.acceptedEvents = acceptedEvents;
this.nativeEvents = nativeEvents;
}
/** Combines accepted events from a number of deserializers */
protected static EnumSet allAcceptedEvents(JsonpDeserializer>... deserializers) {
EnumSet result = EnumSet.noneOf(Event.class);
for (JsonpDeserializer> deserializer: deserializers) {
EnumSet set = deserializer.acceptedEvents();
// Disabled for now. Only happens with the experimental Union2 and is caused by string and number
// parsers leniency. Need to be replaced with a check on a preferred event type.
//if (!Collections.disjoint(result, set)) {
// throw new IllegalArgumentException("Deserializer accepted events are not disjoint");
//}
result.addAll(set);
}
return result;
}
@Override
public EnumSet nativeEvents() {
return nativeEvents;
}
/**
* The JSON events this deserializer accepts as a starting point
*/
public final EnumSet acceptedEvents() {
return acceptedEvents;
}
/**
* Convenience method for {@code acceptedEvents.contains(event)}
*/
public final boolean accepts(Event event) {
return acceptedEvents.contains(event);
}
//---------------------------------------------------------------------------------------------
//----- Builtin types
static final JsonpDeserializer STRING =
// String parsing is lenient and accepts any other primitive type
new JsonpDeserializerBase(EnumSet.of(
Event.KEY_NAME, Event.VALUE_STRING, Event.VALUE_NUMBER,
Event.VALUE_FALSE, Event.VALUE_TRUE
),
EnumSet.of(Event.VALUE_STRING)
) {
@Override
public String deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_TRUE) {
return "true";
}
if (event == Event.VALUE_FALSE) {
return "false";
}
return parser.getString(); // also accepts numbers
}
};
static final JsonpDeserializer INTEGER =
new JsonpDeserializerBase(
EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_STRING),
EnumSet.of(Event.VALUE_NUMBER)
) {
@Override
public Integer deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_STRING) {
return Integer.valueOf(parser.getString());
}
return parser.getInt();
}
};
static final JsonpDeserializer BOOLEAN =
new JsonpDeserializerBase(
EnumSet.of(Event.VALUE_FALSE, Event.VALUE_TRUE, Event.VALUE_STRING),
EnumSet.of(Event.VALUE_FALSE, Event.VALUE_TRUE)
) {
@Override
public Boolean deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_STRING) {
return Boolean.parseBoolean(parser.getString());
} else {
return event == Event.VALUE_TRUE;
}
}
};
static final JsonpDeserializer LONG =
new JsonpDeserializerBase(
EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_STRING),
EnumSet.of(Event.VALUE_NUMBER)
) {
@Override
public Long deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_STRING) {
return Long.valueOf(parser.getString());
}
return parser.getLong();
}
};
static final JsonpDeserializer FLOAT =
new JsonpDeserializerBase(
EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_STRING),
EnumSet.of(Event.VALUE_NUMBER)
) {
@Override
public Float deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_STRING) {
return Float.valueOf(parser.getString());
}
return parser.getBigDecimal().floatValue();
}
};
static final JsonpDeserializer DOUBLE =
new JsonpDeserializerBase(
EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_STRING),
EnumSet.of(Event.VALUE_NUMBER)
) {
@Override
public Double deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_STRING) {
return Double.valueOf(parser.getString());
}
return parser.getBigDecimal().doubleValue();
}
};
static final class DoubleOrNullDeserializer extends JsonpDeserializerBase {
static final EnumSet nativeEvents = EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_NULL);
static final EnumSet acceptedEvents = EnumSet.of(Event.VALUE_STRING, Event.VALUE_NUMBER, Event.VALUE_NULL);
private final double defaultValue;
DoubleOrNullDeserializer(double defaultValue) {
super(acceptedEvents, nativeEvents);
this.defaultValue = defaultValue;
}
@Override
public Double deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_NULL) {
return defaultValue;
}
if (event == Event.VALUE_STRING) {
return Double.valueOf(parser.getString());
}
return parser.getBigDecimal().doubleValue();
}
}
static final class IntOrNullDeserializer extends JsonpDeserializerBase {
static final EnumSet nativeEvents = EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_NULL);
static final EnumSet acceptedEvents = EnumSet.of(Event.VALUE_STRING, Event.VALUE_NUMBER, Event.VALUE_NULL);
private final int defaultValue;
IntOrNullDeserializer(int defaultValue) {
super(acceptedEvents, nativeEvents);
this.defaultValue = defaultValue;
}
@Override
public Integer deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_NULL) {
return defaultValue;
}
if (event == Event.VALUE_STRING) {
return Integer.valueOf(parser.getString());
}
return parser.getInt();
}
}
static final JsonpDeserializer DOUBLE_OR_NAN =
new JsonpDeserializerBase(
EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_STRING, Event.VALUE_NULL),
EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_NULL)
) {
@Override
public Double deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_NULL) {
return Double.NaN;
}
if (event == Event.VALUE_STRING) {
return Double.valueOf(parser.getString());
}
return parser.getBigDecimal().doubleValue();
}
};
static final JsonpDeserializer NUMBER =
new JsonpDeserializerBase(
EnumSet.of(Event.VALUE_NUMBER, Event.VALUE_STRING),
EnumSet.of(Event.VALUE_NUMBER)
) {
@Override
public Number deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.VALUE_STRING) {
return Double.valueOf(parser.getString());
}
return ((JsonNumber)parser.getValue()).numberValue();
}
};
static final JsonpDeserializer JSON_VALUE =
new JsonpDeserializerBase(
EnumSet.allOf(Event.class)
) {
@Override
public JsonValue deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
return parser.getValue();
}
};
static final JsonpDeserializer VOID = new JsonpDeserializerBase(
EnumSet.allOf(Event.class)
) {
@Override
public Void deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
JsonpUtils.skipValue(parser, event);
return null;
}
};
//----- Collections
static class ArrayDeserializer implements JsonpDeserializer> {
private final JsonpDeserializer itemDeserializer;
private EnumSet acceptedEvents;
private static final EnumSet nativeEvents = EnumSet.of(Event.START_ARRAY);
protected ArrayDeserializer(JsonpDeserializer itemDeserializer) {
this.itemDeserializer = itemDeserializer;
}
@Override
public EnumSet nativeEvents() {
return nativeEvents;
}
@Override
public EnumSet acceptedEvents() {
// Accepted events is computed lazily
// no need for double-checked lock, we don't care about computing it several times
if (acceptedEvents == null) {
acceptedEvents = EnumSet.of(Event.START_ARRAY);
acceptedEvents.addAll(itemDeserializer.acceptedEvents());
}
return acceptedEvents;
}
@Override
public List deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
if (event == Event.START_ARRAY) {
List result = new ArrayList<>();
try {
while ((event = parser.next()) != Event.END_ARRAY) {
// JSON null: add null unless the deserializer can handle it
if (event == Event.VALUE_NULL && !itemDeserializer.accepts(event)) {
result.add(null);
} else {
JsonpUtils.ensureAccepts(itemDeserializer, parser, event);
result.add(itemDeserializer.deserialize(parser, mapper, event));
}
}
} catch (Exception e) {
throw JsonpMappingException.from(e, result.size(), parser);
}
return result;
} else {
// Single-value mode
JsonpUtils.ensureAccepts(itemDeserializer, parser, event);
return Collections.singletonList(itemDeserializer.deserialize(parser, mapper, event));
}
}
}
static class StringMapDeserializer extends JsonpDeserializerBase
© 2015 - 2025 Weber Informatics LLC | Privacy Policy