Skip to content

Commit 007d715

Browse files
Add mapping exception with JSON path and location (#234) (#237)
Co-authored-by: Sylvain Wallez <sylvain@elastic.co>
1 parent fd3be11 commit 007d715

15 files changed

+591
-134
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package co.elastic.clients.json;
21+
22+
import jakarta.json.JsonArray;
23+
import jakarta.json.JsonObject;
24+
import jakarta.json.JsonValue;
25+
import jakarta.json.stream.JsonLocation;
26+
import jakarta.json.stream.JsonParser;
27+
28+
import java.math.BigDecimal;
29+
import java.util.Map;
30+
import java.util.stream.Stream;
31+
32+
public abstract class DelegatingJsonParser implements JsonParser {
33+
34+
private final JsonParser parser;
35+
36+
public DelegatingJsonParser(JsonParser parser) {
37+
this.parser = parser;
38+
}
39+
40+
@Override
41+
public boolean hasNext() {
42+
return parser.hasNext();
43+
}
44+
45+
@Override
46+
public Event next() {
47+
return parser.next();
48+
}
49+
50+
@Override
51+
public String getString() {
52+
return parser.getString();
53+
}
54+
55+
@Override
56+
public boolean isIntegralNumber() {
57+
return parser.isIntegralNumber();
58+
}
59+
60+
@Override
61+
public int getInt() {
62+
return parser.getInt();
63+
}
64+
65+
@Override
66+
public long getLong() {
67+
return parser.getLong();
68+
}
69+
70+
@Override
71+
public BigDecimal getBigDecimal() {
72+
return parser.getBigDecimal();
73+
}
74+
75+
@Override
76+
public JsonLocation getLocation() {
77+
return parser.getLocation();
78+
}
79+
80+
@Override
81+
public JsonObject getObject() {
82+
return parser.getObject();
83+
}
84+
85+
@Override
86+
public JsonValue getValue() {
87+
return parser.getValue();
88+
}
89+
90+
@Override
91+
public JsonArray getArray() {
92+
return parser.getArray();
93+
}
94+
95+
@Override
96+
public Stream<JsonValue> getArrayStream() {
97+
return parser.getArrayStream();
98+
}
99+
100+
@Override
101+
public Stream<Map.Entry<String, JsonValue>> getObjectStream() {
102+
return parser.getObjectStream();
103+
}
104+
105+
@Override
106+
public Stream<JsonValue> getValueStream() {
107+
return parser.getValueStream();
108+
}
109+
110+
@Override
111+
public void skipArray() {
112+
parser.skipArray();
113+
}
114+
115+
@Override
116+
public void skipObject() {
117+
parser.skipObject();
118+
}
119+
120+
@Override
121+
public void close() {
122+
parser.close();
123+
}
124+
}

java-client/src/main/java/co/elastic/clients/json/DelegatingJsonpMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
import javax.annotation.Nullable;
2727

28-
public class DelegatingJsonpMapper implements JsonpMapper {
28+
public abstract class DelegatingJsonpMapper implements JsonpMapper {
2929

3030
protected final JsonpMapper mapper;
3131

java-client/src/main/java/co/elastic/clients/json/ExternallyTaggedUnion.java

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import co.elastic.clients.util.TaggedUnion;
2323
import jakarta.json.stream.JsonGenerator;
2424
import jakarta.json.stream.JsonParser;
25-
import jakarta.json.stream.JsonParsingException;
2625

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

6867
return unionCtor.apply(type, deserializer.deserialize(parser, mapper, event));
@@ -97,7 +96,7 @@ public Map<String, Union> deserialize(JsonParser parser, JsonpMapper mapper, Eve
9796
public void deserializeEntry(String key, JsonParser parser, JsonpMapper mapper, Map<String, Union> targetMap) {
9897
int hashPos = key.indexOf('#');
9998
if (hashPos == -1) {
100-
throw new JsonParsingException(
99+
throw new JsonpMappingException(
101100
"Property name '" + key + "' is not in the 'type#name' format. Make sure the request has 'typed_keys' set.",
102101
parser.getLocation()
103102
);
@@ -117,27 +116,36 @@ public void deserializeEntry(String key, JsonParser parser, JsonpMapper mapper,
117116
EnumSet.of(Event.START_OBJECT),
118117
(parser, mapper, event) -> {
119118
Map<String, List<T>> result = new HashMap<>();
120-
while ((event = parser.next()) != Event.END_OBJECT) {
121-
JsonpUtils.expectEvent(parser, event, Event.KEY_NAME);
122-
// Split key and type
123-
String key = parser.getString();
124-
int hashPos = key.indexOf('#');
125-
if (hashPos == -1) {
126-
throw new JsonParsingException(
127-
"Property name '" + key + "' is not in the 'type#name' format. Make sure the request has 'typed_keys' set.",
128-
parser.getLocation()
129-
);
119+
String key = null;
120+
try {
121+
while ((event = parser.next()) != Event.END_OBJECT) {
122+
JsonpUtils.expectEvent(parser, event, Event.KEY_NAME);
123+
// Split key and type
124+
key = parser.getString();
125+
int hashPos = key.indexOf('#');
126+
if (hashPos == -1) {
127+
throw new JsonpMappingException(
128+
"Property name '" + key + "' is not in the 'type#name' format. Make sure the request has 'typed_keys' set.",
129+
parser.getLocation()
130+
).prepend(null, key);
131+
}
132+
133+
String type = key.substring(0, hashPos);
134+
String name = key.substring(hashPos + 1);
135+
136+
List<T> list = new ArrayList<>();
137+
JsonpUtils.expectNextEvent(parser, Event.START_ARRAY);
138+
try {
139+
while ((event = parser.next()) != Event.END_ARRAY) {
140+
list.add(deserializer.deserializer.deserialize(type, parser, mapper, event));
141+
}
142+
} catch (Exception e) {
143+
throw JsonpMappingException.from(e, list.size(), parser);
144+
}
145+
result.put(name, list);
130146
}
131-
132-
String type = key.substring(0, hashPos);
133-
String name = key.substring(hashPos + 1);
134-
135-
List<T> list = new ArrayList<>();
136-
JsonpUtils.expectNextEvent(parser, Event.START_ARRAY);
137-
while ((event = parser.next()) != Event.END_ARRAY) {
138-
list.add(deserializer.deserializer.deserialize(type, parser, mapper, event));
139-
}
140-
result.put(name, list);
147+
} catch (Exception e) {
148+
throw JsonpMappingException.from(e, null, key, parser);
141149
}
142150
return result;
143151
}

java-client/src/main/java/co/elastic/clients/json/JsonEnum.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public T deserialize(JsonParser parser, JsonpMapper mapper, JsonParser.Event eve
8585
public T deserialize(String value, JsonParser parser) {
8686
T result = this.lookupTable.get(value);
8787
if (result == null) {
88-
throw new JsonParsingException("Invalid enum '" + value + "'", parser.getLocation());
88+
throw new JsonpMappingException("Invalid enum '" + value + "'", parser.getLocation());
8989
}
9090
return result;
9191
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package co.elastic.clients.json;
21+
22+
import jakarta.json.stream.JsonLocation;
23+
24+
class JsonLocationImpl implements JsonLocation {
25+
26+
private final long columnNo;
27+
private final long lineNo;
28+
private final long offset;
29+
30+
JsonLocationImpl(long lineNo, long columnNo, long streamOffset) {
31+
this.lineNo = lineNo;
32+
this.columnNo = columnNo;
33+
this.offset = streamOffset;
34+
}
35+
36+
@Override
37+
public long getLineNumber() {
38+
return lineNo;
39+
}
40+
41+
@Override
42+
public long getColumnNumber() {
43+
return columnNo;
44+
}
45+
46+
@Override
47+
public long getStreamOffset() {
48+
return offset;
49+
}
50+
51+
@Override
52+
public String toString() {
53+
return "(line no=" + lineNo + ", column no=" + columnNo + ", offset=" + offset + ")";
54+
}
55+
}

java-client/src/main/java/co/elastic/clients/json/JsonpDeserializer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,6 @@ static <T> JsonpDeserializer<Map<String, T>> stringMapDeserializer(JsonpDeserial
214214
static <K extends JsonEnum, V> JsonpDeserializer<Map<K, V>> enumMapDeserializer(
215215
JsonpDeserializer<K> keyDeserializer, JsonpDeserializer<V> valueDeserializer
216216
) {
217-
return new JsonpDeserializerBase.EnumMapDeserializer<K, V>(keyDeserializer, valueDeserializer);
217+
return new JsonpDeserializerBase.EnumMapDeserializer<>(keyDeserializer, valueDeserializer);
218218
}
219219
}

0 commit comments

Comments
 (0)