Skip to content

Commit

Permalink
Add buffered JsonData implementation for Jackson (#567) (#569)
Browse files Browse the repository at this point in the history
Co-authored-by: Sylvain Wallez <[email protected]>
  • Loading branch information
github-actions[bot] and swallez authored May 5, 2023
1 parent 2a15227 commit 4e7916b
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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.JsonParser;

public interface BufferingJsonParser extends JsonParser {

/**
* Get the value at the current parser position as a <code>JsonData</code> object.
* @return
*/
JsonData getJsonData();

}
33 changes: 33 additions & 0 deletions java-client/src/main/java/co/elastic/clients/json/JsonBuffer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.JsonParser;

/**
* A buffer of JSON events.
*/
public interface JsonBuffer {

/**
* Get the contents of this buffer as a JSON parser. Can be called multiple times.
*/
JsonParser asParser();
}
17 changes: 12 additions & 5 deletions java-client/src/main/java/co/elastic/clients/json/JsonData.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ public interface JsonData extends JsonpSerializable {
*
* @throws IllegalStateException if no mapper was provided at creation time.
*/
<T> T to(Class<T> clazz);
default <T> T to(Class<T> clazz) {
return to((Type)clazz);
}

/**
* Converts this object to a target type. A mapper must have been provided at creation time.
Expand All @@ -70,7 +72,9 @@ public interface JsonData extends JsonpSerializable {
/**
* Converts this object to a target class.
*/
<T> T to(Class<T> clazz, JsonpMapper mapper);
default <T> T to(Class<T> clazz, JsonpMapper mapper) {
return to((Type)clazz, mapper);
}

/**
* Converts this object to a target type.
Expand Down Expand Up @@ -145,8 +149,7 @@ static JsonData from(InputStream json) {
* {@link #deserialize(JsonpDeserializer)}.
*/
static JsonData from(JsonParser parser, JsonpMapper mapper) {
parser.next(); // Need to be at the beginning of the value to read
return of(parser.getValue(), mapper);
return from(parser, mapper, parser.next());
}

/**
Expand All @@ -155,7 +158,11 @@ static JsonData from(JsonParser parser, JsonpMapper mapper) {
* {@link #deserialize(JsonpDeserializer)}.
*/
static JsonData from(JsonParser parser, JsonpMapper mapper, JsonParser.Event event) {
return of(parser.getValue(), mapper);
if (parser instanceof BufferingJsonParser) {
return ((BufferingJsonParser)parser).getJsonData();
} else {
return of(parser.getValue(), mapper);
}
}

JsonpDeserializer<JsonData> _DESERIALIZER = JsonpDeserializer.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,11 @@ public JsonValue toJson(JsonpMapper mapper) {
return parser.getValue();
}

@Override
public <T> T to(Class<T> clazz) {
return to((Type)clazz, null);
}

@Override
public <T> T to(Type clazz) {
return to(clazz, null);
}

@Override
public <T> T to(Class<T> clazz, JsonpMapper mapper) {
return to((Type)clazz, mapper);
}

@Override
public <T> T to(Type type, JsonpMapper mapper) {
if (type instanceof Class<?> && ((Class<?>)type).isAssignableFrom(value.getClass())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,13 @@ public static void skipValue(JsonParser parser, Event event) {
}
}

/**
* Copy the JSON value at the current parser location to a JSON generator.
*/
public static void copy(JsonParser parser, JsonGenerator generator) {
copy(parser, generator, parser.next());
}

/**
* Copy the JSON value at the current parser location to a JSON generator.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* 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.jackson;

import co.elastic.clients.json.JsonBuffer;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.json.JsonpDeserializer;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.JsonpUtils;
import com.fasterxml.jackson.databind.util.TokenBuffer;
import jakarta.json.JsonValue;
import jakarta.json.stream.JsonGenerator;
import jakarta.json.stream.JsonParser;

import java.io.IOException;
import java.lang.reflect.Type;

class JacksonJsonBuffer implements JsonBuffer, JsonData {
private final TokenBuffer buffer;
private final JacksonJsonpMapper mapper;

JacksonJsonBuffer(TokenBuffer buffer, JacksonJsonpMapper mapper) {
this.buffer = buffer;
this.mapper = mapper;
}

@Override
public JsonParser asParser() {
return new JacksonJsonpParser(buffer.asParser(), mapper);
}

@Override
public JsonValue toJson() {
try (JsonParser parser = asParser()) {
parser.next(); // move to first event
return parser.getValue();
}
}

@Override
public JsonValue toJson(JsonpMapper mapper) {
// We don't need the mapper
return toJson();
}

@Override
public <T> T to(Type type) {
return to(type, this.mapper);
}

@Override
public <T> T to(Type type, JsonpMapper mapper) {
try (JsonParser parser = asParser()) {
return mapper.deserialize(parser, type);
}
}

@Override
public <T> T deserialize(JsonpDeserializer<T> deserializer) {
return deserialize(deserializer, this.mapper);
}

@Override
public <T> T deserialize(JsonpDeserializer<T> deserializer, JsonpMapper mapper) {
try (JsonParser parser = asParser()) {
return deserializer.deserialize(parser, mapper);
}
}

@Override
public void serialize(JsonGenerator generator, JsonpMapper mapper) {
if (generator instanceof JacksonJsonpGenerator) {
JacksonJsonpGenerator jkGenerator = (JacksonJsonpGenerator) generator;
try {
buffer.serialize(jkGenerator.jacksonGenerator());
} catch (IOException e) {
throw JacksonUtils.convertException(e);
}
} else {
try (JsonParser parser = asParser()) {
JsonpUtils.copy(parser, generator);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,20 @@
*/
public class JacksonJsonProvider extends JsonProvider {

private final JacksonJsonpMapper mapper;
private final JsonFactory jsonFactory;

public JacksonJsonProvider(JsonFactory jsonFactory) {
this.jsonFactory = jsonFactory;
public JacksonJsonProvider(JacksonJsonpMapper mapper) {
this.mapper = mapper;
this.jsonFactory = mapper.objectMapper().getFactory();
}

public JacksonJsonProvider() {
this(new JsonFactory());
this(new JacksonJsonpMapper());
}

/**
* Return the underlying Jackson {@link JsonFactory}.
*/
public JsonFactory jacksonJsonFactory() {
return this.jsonFactory;
public JacksonJsonpMapper mapper() {
return this.mapper;
}

//---------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -105,7 +104,7 @@ private class ParserFactory implements JsonParserFactory {
@Override
public JsonParser createParser(Reader reader) {
try {
return new JacksonJsonpParser(jsonFactory.createParser(reader));
return new JacksonJsonpParser(jsonFactory.createParser(reader), mapper);
} catch (IOException ioe) {
throw JacksonUtils.convertException(ioe);
}
Expand All @@ -114,7 +113,7 @@ public JsonParser createParser(Reader reader) {
@Override
public JsonParser createParser(InputStream in) {
try {
return new JacksonJsonpParser(jsonFactory.createParser(in));
return new JacksonJsonpParser(jsonFactory.createParser(in), mapper);
} catch (IOException ioe) {
throw JacksonUtils.convertException(ioe);
}
Expand All @@ -123,7 +122,7 @@ public JsonParser createParser(InputStream in) {
@Override
public JsonParser createParser(InputStream in, Charset charset) {
try {
return new JacksonJsonpParser(jsonFactory.createParser(new InputStreamReader(in, charset)));
return new JacksonJsonpParser(jsonFactory.createParser(new InputStreamReader(in, charset)), mapper);
} catch (IOException ioe) {
throw JacksonUtils.convertException(ioe);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ private JacksonJsonpMapper(ObjectMapper objectMapper, JacksonJsonProvider provid
}

public JacksonJsonpMapper(ObjectMapper objectMapper) {
this(objectMapper,
// Creating the json factory from the mapper ensures it will be returned by JsonParser.getCodec()
new JacksonJsonProvider(objectMapper.getFactory())
);
this.objectMapper = objectMapper;
// Order is important as JacksonJsonProvider(this) will get ObjectMapper
this.provider = new JacksonJsonProvider(this);
}

public JacksonJsonpMapper() {
Expand Down
Loading

0 comments on commit 4e7916b

Please sign in to comment.