-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds a declarative JSON configuration object that allows users to specify the schema of a JSON message. It is meant to have good out-of-the-box defaults, while still allowing power users to modify some of the finer parsing details (should this int field be parseable from a string? should null values be allowed? what if a field is missing? etc). The JSON configuration layer is not tied to any specific implementation; it is introspectible, and could have alternative implementations with other parsing backends. (I could imagine a DHE use-case where they do code-generation based on the JSON configuration, somewhat like the DHE avro ObjectProcessor code generator.) Out of the box, there's an ObjectProcessor implementation based on the Jackson streaming APIs; that is, the data flows from byte[]s (or InputStream, relevant for very-large-files) to the output WritableChunks without the need for the intermediating Jackson databind layer (TreeNode). This saves a large layer of allocation that our current kafka json_spec layer relies upon. The ObjectProcessor layer means that this can be used in other places that expose ObjectProcessor layers and want 1-to-1 record-to-row (currently, Kafka). Part of #5222
- Loading branch information
1 parent
b1f657b
commit 1320749
Showing
127 changed files
with
11,931 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
engine/processor/src/main/java/io/deephaven/processor/NamedObjectProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// | ||
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending | ||
// | ||
package io.deephaven.processor; | ||
|
||
import io.deephaven.annotations.BuildableStyle; | ||
import io.deephaven.qst.type.Type; | ||
import org.immutables.value.Value.Check; | ||
import org.immutables.value.Value.Immutable; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
@Immutable | ||
@BuildableStyle | ||
public abstract class NamedObjectProcessor<T> { | ||
|
||
public static <T> Builder<T> builder() { | ||
return ImmutableNamedObjectProcessor.builder(); | ||
} | ||
|
||
public static <T> NamedObjectProcessor<T> of(ObjectProcessor<? super T> processor, String... names) { | ||
return NamedObjectProcessor.<T>builder().processor(processor).addNames(names).build(); | ||
} | ||
|
||
public static <T> NamedObjectProcessor<T> of(ObjectProcessor<? super T> processor, Iterable<String> names) { | ||
return NamedObjectProcessor.<T>builder().processor(processor).addAllNames(names).build(); | ||
} | ||
|
||
public static <T> NamedObjectProcessor<T> prefix(ObjectProcessor<T> processor, String prefix) { | ||
final int size = processor.size(); | ||
if (size == 1) { | ||
return of(processor, prefix); | ||
} | ||
return of(processor, IntStream.range(0, size).mapToObj(ix -> prefix + "_" + ix).collect(Collectors.toList())); | ||
} | ||
|
||
/** | ||
* The name for each output of {@link #processor()}. | ||
*/ | ||
public abstract List<String> names(); | ||
|
||
/** | ||
* The object processor. | ||
*/ | ||
public abstract ObjectProcessor<? super T> processor(); | ||
|
||
public interface Builder<T> { | ||
Builder<T> processor(ObjectProcessor<? super T> processor); | ||
|
||
Builder<T> addNames(String element); | ||
|
||
Builder<T> addNames(String... elements); | ||
|
||
Builder<T> addAllNames(Iterable<String> elements); | ||
|
||
NamedObjectProcessor<T> build(); | ||
} | ||
|
||
public interface Provider extends ObjectProcessor.Provider { | ||
|
||
/** | ||
* The name for each output of the processors. Equivalent to the named processors' | ||
* {@link NamedObjectProcessor#names()}. | ||
* | ||
* @return the names | ||
*/ | ||
List<String> names(); | ||
|
||
/** | ||
* Creates a named object processor that can process the {@code inputType}. This will successfully create a | ||
* named processor when {@code inputType} is one of, or extends from one of, {@link #inputTypes()}. Otherwise, | ||
* an {@link IllegalArgumentException} will be thrown. Equivalent to | ||
* {@code NamedObjectProcessor.of(processor(inputType), names())}. | ||
* | ||
* @param inputType the input type | ||
* @return the object processor | ||
* @param <T> the input type | ||
*/ | ||
default <T> NamedObjectProcessor<? super T> named(Type<T> inputType) { | ||
return NamedObjectProcessor.of(processor(inputType), names()); | ||
} | ||
} | ||
|
||
@Check | ||
final void checkSizes() { | ||
if (names().size() != processor().size()) { | ||
throw new IllegalArgumentException( | ||
String.format("Unmatched sizes; columnNames().size()=%d, processor().size()=%d", | ||
names().size(), processor().size())); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
plugins { | ||
id 'java-library' | ||
id 'io.deephaven.project.register' | ||
} | ||
|
||
dependencies { | ||
api project(':extensions-json-jackson') | ||
api project(':engine-processor') | ||
api 'de.undercouch:bson4jackson:2.15.1' | ||
|
||
Classpaths.inheritImmutables(project) | ||
compileOnly 'com.google.code.findbugs:jsr305:3.0.2' | ||
|
||
Classpaths.inheritJacksonPlatform(project, 'testImplementation') | ||
Classpaths.inheritJUnitPlatform(project) | ||
Classpaths.inheritAssertJ(project) | ||
testImplementation 'org.junit.jupiter:junit-jupiter' | ||
testImplementation 'com.fasterxml.jackson.core:jackson-databind' | ||
} | ||
|
||
test { | ||
useJUnitPlatform() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
io.deephaven.project.ProjectType=JAVA_PUBLIC |
30 changes: 30 additions & 0 deletions
30
...nsions/bson-jackson/src/main/java/io/deephaven/bson/jackson/JacksonBsonConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending | ||
// | ||
package io.deephaven.bson.jackson; | ||
|
||
import com.fasterxml.jackson.core.ObjectCodec; | ||
import de.undercouch.bson4jackson.BsonFactory; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
|
||
final class JacksonBsonConfiguration { | ||
private static final BsonFactory DEFAULT_FACTORY; | ||
|
||
static { | ||
// We'll attach an ObjectMapper if it's on the classpath, this allows parsing of AnyOptions | ||
ObjectCodec objectCodec = null; | ||
try { | ||
final Class<?> clazz = Class.forName("com.fasterxml.jackson.databind.ObjectMapper"); | ||
objectCodec = (ObjectCodec) clazz.getDeclaredConstructor().newInstance(); | ||
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | ||
| InvocationTargetException e) { | ||
// ignore | ||
} | ||
DEFAULT_FACTORY = new BsonFactory(objectCodec); | ||
} | ||
|
||
static BsonFactory defaultFactory() { | ||
return DEFAULT_FACTORY; | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
extensions/bson-jackson/src/main/java/io/deephaven/bson/jackson/JacksonBsonProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending | ||
// | ||
package io.deephaven.bson.jackson; | ||
|
||
import de.undercouch.bson4jackson.BsonFactory; | ||
import io.deephaven.json.ValueOptions; | ||
import io.deephaven.json.jackson.JacksonProvider; | ||
|
||
public final class JacksonBsonProvider { | ||
|
||
/** | ||
* Creates a jackson BSON provider using a default factory. | ||
* | ||
* @param options the object options | ||
* @return the jackson BSON provider | ||
* @see #of(ValueOptions, BsonFactory) | ||
*/ | ||
public static JacksonProvider of(ValueOptions options) { | ||
return of(options, JacksonBsonConfiguration.defaultFactory()); | ||
} | ||
|
||
/** | ||
* Creates a jackson BSON provider using the provided {@code factory}. | ||
* | ||
* @param options the object options | ||
* @param factory the jackson BSON factory | ||
* @return the jackson BSON provider | ||
*/ | ||
public static JacksonProvider of(ValueOptions options, BsonFactory factory) { | ||
return JacksonProvider.of(options, factory); | ||
} | ||
} |
Oops, something went wrong.