Skip to content

Commit

Permalink
Add mapping exception with JSON path and location (#234) (#235)
Browse files Browse the repository at this point in the history
Co-authored-by: Sylvain Wallez <sylvain@elastic.co>
  • Loading branch information
github-actions[bot] and swallez authored Apr 1, 2022
1 parent dfaad0a commit c3f679c
Show file tree
Hide file tree
Showing 15 changed files with 591 additions and 134 deletions.
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

0 comments on commit c3f679c

Please sign in to comment.