Skip to content

[Backport 8.8] Add buffered JsonData implementation for Jackson #569

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

Merged
merged 1 commit into from
May 5, 2023
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,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