A content processing library for Elasticsearch that provides abstractions for parsing and generating various content formats including JSON, YAML, CBOR, and Smile.
—
The X-Content library provides pull-parsing capabilities for efficiently reading and navigating structured content with support for streaming operations across multiple formats.
Core interface for pull-based parsing of structured content.
public interface XContentParser extends Closeable {
/**
* Parser tokens representing different content elements
*/
enum Token {
START_OBJECT, // {
END_OBJECT, // }
START_ARRAY, // [
END_ARRAY, // ]
FIELD_NAME, // field name in an object
VALUE_STRING, // string value
VALUE_NUMBER, // numeric value
VALUE_BOOLEAN, // boolean value
VALUE_EMBEDDED_OBJECT, // binary/embedded object
VALUE_NULL; // null value
/**
* Check if this token represents a value
* @return true if this token is a value token
*/
public boolean isValue();
}
/**
* Number types for numeric values
*/
enum NumberType {
INT, LONG, FLOAT, DOUBLE, BIG_INTEGER, BIG_DECIMAL
}
/**
* Advance to the next token
* @return the next token, or null if end of content
*/
Token nextToken() throws IOException;
/**
* Get the current token without advancing
* @return the current token
*/
Token currentToken();
/**
* Get the name of the current field (when currentToken is FIELD_NAME)
* @return the field name
*/
String currentName() throws IOException;
/**
* Advance to next token and return field name if it's FIELD_NAME
* @return field name if next token is FIELD_NAME, null otherwise
*/
String nextFieldName() throws IOException;
/**
* Skip all children of the current token (if it's START_OBJECT or START_ARRAY)
*/
void skipChildren() throws IOException;
/**
* Get the text representation of the current value
* @return text value of current token
*/
String text() throws IOException;
/**
* Get the text representation of the current value, or null if null token
* @return text value or null
*/
String textOrNull() throws IOException;
/**
* Get the current value as a generic Number
* @return Number representation of current numeric value
*/
Number numberValue() throws IOException;
/**
* Get the type of the current numeric value
* @return NumberType of current numeric value
*/
NumberType numberType() throws IOException;
/**
* Get the current value as an integer
* @return integer value
*/
int intValue() throws IOException;
/**
* Get the current value as a long
* @return long value
*/
long longValue() throws IOException;
/**
* Get the current value as a float
* @return float value
*/
float floatValue() throws IOException;
/**
* Get the current value as a double
* @return double value
*/
double doubleValue() throws IOException;
/**
* Get the current value as a boolean
* @return boolean value
*/
boolean booleanValue() throws IOException;
/**
* Get the current value as a byte array (for binary data)
* @return byte array
*/
byte[] binaryValue() throws IOException;
/**
* Parse the current object into a Map
* @return Map representation of current object
*/
Map<String, Object> map() throws IOException;
/**
* Parse the current object into a Map with specific ordering
* @param ordered whether to preserve field ordering
* @return Map representation of current object
*/
Map<String, Object> mapOrdered() throws IOException;
/**
* Parse the current array into a List
* @return List representation of current array
*/
List<Object> list() throws IOException;
/**
* Parse the current array into a List with specific ordering
* @param ordered whether to preserve ordering
* @return List representation of current array
*/
List<Object> listOrderedMap() throws IOException;
/**
* Get the current parsing location for error reporting
* @return XContentLocation with line/column information
*/
XContentLocation getTokenLocation();
/**
* Get the named XContent registry for this parser
* @return NamedXContentRegistry instance
*/
NamedXContentRegistry getXContentRegistry();
/**
* Get the deprecation handler for this parser
* @return DeprecationHandler instance
*/
DeprecationHandler getDeprecationHandler();
/**
* Get the REST API version for this parser
* @return RestApiVersion instance
*/
RestApiVersion getRestApiVersion();
}Usage Examples:
import org.elasticsearch.xcontent.*;
// Basic parsing example
String jsonContent = """
{
"name": "John Doe",
"age": 30,
"active": true,
"skills": ["Java", "Elasticsearch"],
"address": {
"street": "123 Main St",
"city": "New York"
}
}
""";
XContentParser parser = XContentType.JSON.xContent()
.createParser(XContentParserConfiguration.EMPTY, jsonContent);
// Navigate through tokens
while (parser.nextToken() != null) {
XContentParser.Token token = parser.currentToken();
switch (token) {
case FIELD_NAME:
String fieldName = parser.currentName();
System.out.println("Field: " + fieldName);
break;
case VALUE_STRING:
System.out.println("String value: " + parser.text());
break;
case VALUE_NUMBER:
System.out.println("Number value: " + parser.numberValue());
break;
case VALUE_BOOLEAN:
System.out.println("Boolean value: " + parser.booleanValue());
break;
case START_OBJECT:
System.out.println("Starting object");
break;
case END_OBJECT:
System.out.println("Ending object");
break;
case START_ARRAY:
System.out.println("Starting array");
break;
case END_ARRAY:
System.out.println("Ending array");
break;
}
}
parser.close();
// Parse specific field values
parser = XContentType.JSON.xContent()
.createParser(XContentParserConfiguration.EMPTY, jsonContent);
String name = null;
int age = 0;
List<String> skills = new ArrayList<>();
while (parser.nextToken() != null) {
if (parser.currentToken() == XContentParser.Token.FIELD_NAME) {
String fieldName = parser.currentName();
parser.nextToken(); // Move to the value
switch (fieldName) {
case "name":
name = parser.text();
break;
case "age":
age = parser.intValue();
break;
case "skills":
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
skills.add(parser.text());
}
break;
case "address":
// Parse nested object
Map<String, Object> address = parser.map();
System.out.println("Address: " + address);
break;
}
}
}
parser.close();
// Quick conversion to Map/List
parser = XContentType.JSON.xContent()
.createParser(XContentParserConfiguration.EMPTY, jsonContent);
parser.nextToken(); // Move to START_OBJECT
Map<String, Object> map = parser.map();
parser.close();Location information for error reporting and debugging.
/**
* Represents a location in XContent (line and column numbers)
*/
public record XContentLocation(int lineNumber, int columnNumber) {
/**
* Unknown location constant
*/
public static final XContentLocation UNKNOWN = new XContentLocation(-1, -1);
/**
* Get the line number (1-based)
* @return line number, or -1 if unknown
*/
public int lineNumber();
/**
* Get the column number (1-based)
* @return column number, or -1 if unknown
*/
public int columnNumber();
}Methods for creating parsers from different input sources.
public interface XContent {
/**
* Create parser from string content
* @param config parser configuration
* @param content string content to parse
* @return XContentParser instance
*/
XContentParser createParser(XContentParserConfiguration config, String content) throws IOException;
/**
* Create parser from input stream
* @param config parser configuration
* @param is input stream to parse
* @return XContentParser instance
*/
XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException;
/**
* Create parser from byte array
* @param config parser configuration
* @param data byte array to parse
* @return XContentParser instance
*/
XContentParser createParser(XContentParserConfiguration config, byte[] data) throws IOException;
/**
* Create parser from byte array with offset and length
* @param config parser configuration
* @param data byte array to parse
* @param offset starting offset in the array
* @param length number of bytes to parse
* @return XContentParser instance
*/
XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException;
/**
* Create parser from Reader
* @param config parser configuration
* @param reader Reader to parse from
* @return XContentParser instance
*/
XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException;
}Extended parser implementations for specific use cases.
/**
* Parser wrapper that filters content based on include/exclude patterns
*/
public class FilterXContentParser implements XContentParser {
/**
* Create a filtering parser
* @param parser the underlying parser
* @param includes field patterns to include
* @param excludes field patterns to exclude
*/
public FilterXContentParser(XContentParser parser, Set<String> includes, Set<String> excludes);
}
/**
* Parser that flattens nested object structures
*/
public class FlatteningXContentParser implements XContentParser {
/**
* Create a flattening parser
* @param parser the underlying parser
*/
public FlatteningXContentParser(XContentParser parser);
}
/**
* Parser that copies content to another parser while parsing
*/
public class CopyingXContentParser implements XContentParser {
/**
* Create a copying parser
* @param parser the source parser
* @param builder the builder to copy content to
*/
public CopyingXContentParser(XContentParser parser, XContentBuilder builder);
}
/**
* Parser backed by a Map instead of content stream
*/
public class MapXContentParser extends AbstractXContentParser {
/**
* Create a parser from a Map
* @param map the map to parse
* @param registry named content registry
* @param deprecationHandler deprecation handler
* @param contentType content type
*/
public MapXContentParser(NamedXContentRegistry registry, DeprecationHandler deprecationHandler,
Map<String, Object> map, XContentType contentType);
}public class XContentUtils {
/**
* Convert a parser token to its corresponding Object value
* @param parser the parser
* @param token the token to convert
* @return Object representation of the token value
*/
public static Object readValue(XContentParser parser, XContentParser.Token token) throws IOException;
}Install with Tessl CLI
npx tessl i tessl/maven-org-elasticsearch--elasticsearch-x-content