Skip to content

Commit e40757f

Browse files
committed
Add pipe-separated enum list
1 parent a898492 commit e40757f

File tree

4 files changed

+173
-96
lines changed

4 files changed

+173
-96
lines changed

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

Lines changed: 5 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,9 @@
2121

2222
import jakarta.json.stream.JsonGenerator;
2323
import jakarta.json.stream.JsonParser;
24-
import jakarta.json.stream.JsonParsingException;
2524

2625
import javax.annotation.Nullable;
2726
import java.util.EnumSet;
28-
import java.util.HashMap;
29-
import java.util.Map;
30-
import java.util.NoSuchElementException;
31-
32-
import static jakarta.json.stream.JsonParser.Event;
3327

3428
/**
3529
* Base interface for enumerations in API types. Members have a JSON representation and also accept
@@ -48,99 +42,14 @@ default void serialize(JsonGenerator generator, JsonpMapper params) {
4842
generator.write(jsonValue());
4943
}
5044

51-
class Deserializer<T extends JsonEnum> extends JsonpDeserializerBase<T> {
52-
53-
private static final EnumSet<Event> acceptedEvents = EnumSet.of(Event.VALUE_STRING, Event.KEY_NAME);
54-
private static final EnumSet<Event> nativeEvents = EnumSet.of(Event.VALUE_STRING);
55-
56-
private final Map<String, T> lookupTable;
57-
45+
// Moved to JsonEnums. Will be deprecated at some point.
46+
class Deserializer<T extends JsonEnum> extends JsonEnums.Deserializer<T> {
5847
public Deserializer(T[] values) {
59-
this(values, acceptedEvents);
60-
}
61-
62-
protected Deserializer(T[] values, EnumSet<Event> acceptedEvents) {
63-
super(acceptedEvents, nativeEvents);
64-
65-
// Use the same size calculation as in java.lang.Enum.enumConstantDirectory
66-
this.lookupTable = new HashMap<>((int)(values.length / 0.75f) + 1);
67-
for (T member : values) {
68-
String jsonValue = member.jsonValue();
69-
if (jsonValue != null) { // _Custom enum members have a null jsonValue
70-
this.lookupTable.put(jsonValue, member);
71-
}
72-
String[] aliases = member.aliases();
73-
if (aliases != null) {
74-
for (String alias: aliases) {
75-
this.lookupTable.put(alias, member);
76-
}
77-
}
78-
}
79-
}
80-
81-
@Override
82-
public T deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
83-
String value = parser.getString();
84-
return deserialize(value, parser);
48+
super(values);
8549
}
8650

87-
/**
88-
* Get the enum member for a JSON string value
89-
*
90-
* @param value the JSON value
91-
* @param parser parsing context
92-
* @return the enum member
93-
* @throws JsonParsingException if no matching enum was found
94-
*/
95-
public T deserialize(String value, JsonParser parser) {
96-
T result = this.lookupTable.get(value);
97-
if (result == null) {
98-
throw new JsonpMappingException("Invalid enum '" + value + "'", parser.getLocation());
99-
}
100-
return result;
101-
}
102-
103-
/**
104-
* Get the enum member for a JSON string value
105-
*
106-
* @param value the JSON value
107-
* @return the enum member
108-
* @throws IllegalArgumentException if no matching enum was found
109-
*/
110-
public T parse(String value) {
111-
T result = this.lookupTable.get(value);
112-
if (result == null) {
113-
throw new NoSuchElementException("Invalid enum '" + value + "'");
114-
}
115-
return result;
116-
}
117-
118-
/**
119-
* An enum deserializer that also accepts boolean values. Used for a few properties that started as two-state booleans
120-
* and evolved into enums over time.
121-
*/
122-
public static class AllowingBooleans<T extends JsonEnum> extends Deserializer<T> {
123-
124-
private static final EnumSet<Event> acceptedEventsAndBoolean =
125-
EnumSet.of(Event.VALUE_STRING, Event.KEY_NAME, Event.VALUE_TRUE, Event.VALUE_FALSE);
126-
127-
public AllowingBooleans(T[] values) {
128-
super(values, acceptedEventsAndBoolean);
129-
}
130-
131-
@Override
132-
public T deserialize(JsonParser parser, JsonpMapper mapper, Event event) {
133-
String value;
134-
if (event == Event.VALUE_TRUE) {
135-
value = "true";
136-
} else if (event == Event.VALUE_FALSE) {
137-
value = "false";
138-
} else {
139-
value = parser.getString();
140-
}
141-
142-
return deserialize(value, parser);
143-
}
51+
Deserializer(T[] values, EnumSet<JsonParser.Event> acceptedEvents) {
52+
super(values, acceptedEvents);
14453
}
14554
}
14655
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
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.JsonGenerator;
23+
import jakarta.json.stream.JsonParser;
24+
import jakarta.json.stream.JsonParsingException;
25+
26+
import java.util.ArrayList;
27+
import java.util.EnumSet;
28+
import java.util.HashMap;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.NoSuchElementException;
32+
import java.util.stream.Collectors;
33+
34+
public class JsonEnums {
35+
36+
public static class Deserializer<T extends JsonEnum> extends JsonpDeserializerBase<T> {
37+
38+
private static final EnumSet<JsonParser.Event> acceptedEvents =
39+
EnumSet.of(JsonParser.Event.VALUE_STRING, JsonParser.Event.KEY_NAME);
40+
private static final EnumSet<JsonParser.Event> nativeEvents = EnumSet.of(JsonParser.Event.VALUE_STRING);
41+
42+
private final Map<String, T> lookupTable;
43+
44+
public Deserializer(T[] values) {
45+
this(values, acceptedEvents);
46+
}
47+
48+
protected Deserializer(T[] values, EnumSet<JsonParser.Event> acceptedEvents) {
49+
super(acceptedEvents, nativeEvents);
50+
51+
// Use the same size calculation as in java.lang.Enum.enumConstantDirectory
52+
this.lookupTable = new HashMap<>((int)(values.length / 0.75f) + 1);
53+
for (T member : values) {
54+
String jsonValue = member.jsonValue();
55+
if (jsonValue != null) { // _Custom enum members have a null jsonValue
56+
this.lookupTable.put(jsonValue, member);
57+
}
58+
String[] aliases = member.aliases();
59+
if (aliases != null) {
60+
for (String alias: aliases) {
61+
this.lookupTable.put(alias, member);
62+
}
63+
}
64+
}
65+
}
66+
67+
@Override
68+
public T deserialize(JsonParser parser, JsonpMapper mapper, JsonParser.Event event) {
69+
String value = parser.getString();
70+
return deserialize(value, parser);
71+
}
72+
73+
/**
74+
* Get the enum member for a JSON string value
75+
*
76+
* @param value the JSON value
77+
* @param parser parsing context
78+
* @return the enum member
79+
* @throws JsonParsingException if no matching enum was found
80+
*/
81+
public T deserialize(String value, JsonParser parser) {
82+
T result = this.lookupTable.get(value);
83+
if (result == null) {
84+
throw new JsonpMappingException("Invalid enum '" + value + "'", parser.getLocation());
85+
}
86+
return result;
87+
}
88+
89+
/**
90+
* Get the enum member for a JSON string value
91+
*
92+
* @param value the JSON value
93+
* @return the enum member
94+
* @throws IllegalArgumentException if no matching enum was found
95+
*/
96+
public T parse(String value) {
97+
T result = this.lookupTable.get(value);
98+
if (result == null) {
99+
throw new NoSuchElementException("Invalid enum '" + value + "'");
100+
}
101+
return result;
102+
}
103+
104+
/**
105+
* An enum deserializer that also accepts boolean values. Used for a few properties that started as two-state booleans
106+
* and evolved into enums over time.
107+
*/
108+
public static class AllowingBooleans<T extends JsonEnum> extends JsonEnum.Deserializer<T> {
109+
110+
private static final EnumSet<JsonParser.Event> acceptedEventsAndBoolean = EnumSet.of(
111+
JsonParser.Event.VALUE_STRING, JsonParser.Event.KEY_NAME, JsonParser.Event.VALUE_TRUE, JsonParser.Event.VALUE_FALSE
112+
);
113+
114+
public AllowingBooleans(T[] values) {
115+
super(values, acceptedEventsAndBoolean);
116+
}
117+
118+
@Override
119+
public T deserialize(JsonParser parser, JsonpMapper mapper, JsonParser.Event event) {
120+
String value;
121+
if (event == JsonParser.Event.VALUE_TRUE) {
122+
value = "true";
123+
} else if (event == JsonParser.Event.VALUE_FALSE) {
124+
value = "false";
125+
} else {
126+
value = parser.getString();
127+
}
128+
129+
return deserialize(value, parser);
130+
}
131+
}
132+
}
133+
134+
static class PipeSeparatedDeserializer<T extends JsonEnum> extends JsonpDeserializerBase<List<T>> {
135+
private final JsonEnum.Deserializer<T> enumDeserializer;
136+
137+
protected PipeSeparatedDeserializer(JsonEnum.Deserializer<T> enumDeserializer) {
138+
super(EnumSet.of(JsonParser.Event.VALUE_STRING));
139+
this.enumDeserializer = enumDeserializer;
140+
}
141+
142+
@Override
143+
public List<T> deserialize(JsonParser parser, JsonpMapper mapper, JsonParser.Event event) {
144+
String[] values = parser.getString().split("\\|"); // There's a fast path for this kind of regex
145+
146+
List<T> result = new ArrayList<>(values.length);
147+
for (String v : values) {
148+
result.add(enumDeserializer.deserialize(v.trim(), parser));
149+
}
150+
151+
return result;
152+
}
153+
}
154+
155+
public static <T extends JsonEnum> void serializePipeSeparated(List<T> values, JsonGenerator generator) {
156+
if (values.size() == 1) {
157+
generator.write(values.get(0).jsonValue());
158+
} else {
159+
generator.write(values.stream().map(JsonEnum::jsonValue).collect(Collectors.joining("|")));
160+
}
161+
}
162+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ static <K extends JsonEnum, V> JsonpDeserializer<Map<K, V>> enumMapDeserializer(
227227
return new JsonpDeserializerBase.EnumMapDeserializer<>(keyDeserializer, valueDeserializer);
228228
}
229229

230+
static <T extends JsonEnum> JsonpDeserializer<List<T>> pipeSeparatedDeserializer(JsonEnum.Deserializer<T> enumDeserializer) {
231+
return new JsonEnums.PipeSeparatedDeserializer<>(enumDeserializer);
232+
}
233+
230234
/**
231235
* Creates a deserializer that will accept a value both as regular JSON and as JSON-in-a-string.
232236
*/
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
package co.elastic.clients.json.jackson;public class JsonEnumTest {
2+
}

0 commit comments

Comments
 (0)