Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 7.17] Add mapping exception with JSON path and location #235

Merged
merged 1 commit into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* 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.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
import jakarta.json.stream.JsonLocation;
import jakarta.json.stream.JsonParser;

import java.math.BigDecimal;
import java.util.Map;
import java.util.stream.Stream;

public abstract class DelegatingJsonParser implements JsonParser {

private final JsonParser parser;

public DelegatingJsonParser(JsonParser parser) {
this.parser = parser;
}

@Override
public boolean hasNext() {
return parser.hasNext();
}

@Override
public Event next() {
return parser.next();
}

@Override
public String getString() {
return parser.getString();
}

@Override
public boolean isIntegralNumber() {
return parser.isIntegralNumber();
}

@Override
public int getInt() {
return parser.getInt();
}

@Override
public long getLong() {
return parser.getLong();
}

@Override
public BigDecimal getBigDecimal() {
return parser.getBigDecimal();
}

@Override
public JsonLocation getLocation() {
return parser.getLocation();
}

@Override
public JsonObject getObject() {
return parser.getObject();
}

@Override
public JsonValue getValue() {
return parser.getValue();
}

@Override
public JsonArray getArray() {
return parser.getArray();
}

@Override
public Stream<JsonValue> getArrayStream() {
return parser.getArrayStream();
}

@Override
public Stream<Map.Entry<String, JsonValue>> getObjectStream() {
return parser.getObjectStream();
}

@Override
public Stream<JsonValue> getValueStream() {
return parser.getValueStream();
}

@Override
public void skipArray() {
parser.skipArray();
}

@Override
public void skipObject() {
parser.skipObject();
}

@Override
public void close() {
parser.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

import javax.annotation.Nullable;

public class DelegatingJsonpMapper implements JsonpMapper {
public abstract class DelegatingJsonpMapper implements JsonpMapper {

protected final JsonpMapper mapper;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import co.elastic.clients.util.TaggedUnion;
import jakarta.json.stream.JsonGenerator;
import jakarta.json.stream.JsonParser;
import jakarta.json.stream.JsonParsingException;

import java.util.ArrayList;
import java.util.EnumSet;
Expand Down Expand Up @@ -62,7 +61,7 @@ public Deserializer(Map<String, JsonpDeserializer<? extends Member>> deserialize
public Union deserialize(String type, JsonParser parser, JsonpMapper mapper, Event event) {
JsonpDeserializer<? extends Member> deserializer = deserializers.get(type);
if (deserializer == null) {
throw new JsonParsingException("Unknown variant type '" + type + "'", parser.getLocation());
throw new JsonpMappingException("Unknown variant type '" + type + "'", parser.getLocation());
}

return unionCtor.apply(type, deserializer.deserialize(parser, mapper, event));
Expand Down Expand Up @@ -97,7 +96,7 @@ public Map<String, Union> deserialize(JsonParser parser, JsonpMapper mapper, Eve
public void deserializeEntry(String key, JsonParser parser, JsonpMapper mapper, Map<String, Union> targetMap) {
int hashPos = key.indexOf('#');
if (hashPos == -1) {
throw new JsonParsingException(
throw new JsonpMappingException(
"Property name '" + key + "' is not in the 'type#name' format. Make sure the request has 'typed_keys' set.",
parser.getLocation()
);
Expand All @@ -117,27 +116,36 @@ public void deserializeEntry(String key, JsonParser parser, JsonpMapper mapper,
EnumSet.of(Event.START_OBJECT),
(parser, mapper, event) -> {
Map<String, List<T>> result = new HashMap<>();
while ((event = parser.next()) != Event.END_OBJECT) {
JsonpUtils.expectEvent(parser, event, Event.KEY_NAME);
// Split key and type
String key = parser.getString();
int hashPos = key.indexOf('#');
if (hashPos == -1) {
throw new JsonParsingException(
"Property name '" + key + "' is not in the 'type#name' format. Make sure the request has 'typed_keys' set.",
parser.getLocation()
);
String key = null;
try {
while ((event = parser.next()) != Event.END_OBJECT) {
JsonpUtils.expectEvent(parser, event, Event.KEY_NAME);
// Split key and type
key = parser.getString();
int hashPos = key.indexOf('#');
if (hashPos == -1) {
throw new JsonpMappingException(
"Property name '" + key + "' is not in the 'type#name' format. Make sure the request has 'typed_keys' set.",
parser.getLocation()
).prepend(null, key);
}

String type = key.substring(0, hashPos);
String name = key.substring(hashPos + 1);

List<T> list = new ArrayList<>();
JsonpUtils.expectNextEvent(parser, Event.START_ARRAY);
try {
while ((event = parser.next()) != Event.END_ARRAY) {
list.add(deserializer.deserializer.deserialize(type, parser, mapper, event));
}
} catch (Exception e) {
throw JsonpMappingException.from(e, list.size(), parser);
}
result.put(name, list);
}

String type = key.substring(0, hashPos);
String name = key.substring(hashPos + 1);

List<T> list = new ArrayList<>();
JsonpUtils.expectNextEvent(parser, Event.START_ARRAY);
while ((event = parser.next()) != Event.END_ARRAY) {
list.add(deserializer.deserializer.deserialize(type, parser, mapper, event));
}
result.put(name, list);
} catch (Exception e) {
throw JsonpMappingException.from(e, null, key, parser);
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public T deserialize(JsonParser parser, JsonpMapper mapper, JsonParser.Event eve
public T deserialize(String value, JsonParser parser) {
T result = this.lookupTable.get(value);
if (result == null) {
throw new JsonParsingException("Invalid enum '" + value + "'", parser.getLocation());
throw new JsonpMappingException("Invalid enum '" + value + "'", parser.getLocation());
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.stream.JsonLocation;

class JsonLocationImpl implements JsonLocation {

private final long columnNo;
private final long lineNo;
private final long offset;

JsonLocationImpl(long lineNo, long columnNo, long streamOffset) {
this.lineNo = lineNo;
this.columnNo = columnNo;
this.offset = streamOffset;
}

@Override
public long getLineNumber() {
return lineNo;
}

@Override
public long getColumnNumber() {
return columnNo;
}

@Override
public long getStreamOffset() {
return offset;
}

@Override
public String toString() {
return "(line no=" + lineNo + ", column no=" + columnNo + ", offset=" + offset + ")";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,6 @@ static <T> JsonpDeserializer<Map<String, T>> stringMapDeserializer(JsonpDeserial
static <K extends JsonEnum, V> JsonpDeserializer<Map<K, V>> enumMapDeserializer(
JsonpDeserializer<K> keyDeserializer, JsonpDeserializer<V> valueDeserializer
) {
return new JsonpDeserializerBase.EnumMapDeserializer<K, V>(keyDeserializer, valueDeserializer);
return new JsonpDeserializerBase.EnumMapDeserializer<>(keyDeserializer, valueDeserializer);
}
}
Loading