CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-jayway-jsonpath--json-path

A Java DSL for reading JSON documents using JsonPath expressions, similar to XPath for XML

Pending
Overview
Eval results
Files

type-handling.mddocs/

Type Handling and Mapping

Type-safe operations and object mapping capabilities for converting JSON data to specific Java types. JsonPath provides several mechanisms for handling generic types and custom object mapping.

Capabilities

Generic Type References

TypeRef class for handling generic types safely, preserving parameterized type information at runtime.

/**
 * Abstract class for specifying generic type information in JsonPath operations
 * Used to preserve generic type parameters that would otherwise be lost due to type erasure
 * @param <T> The target type with full generic information
 */
public abstract class TypeRef<T> implements Comparable<TypeRef<T>> {
    /**
     * Returns the parameterized type information
     * @return Type representing the full generic type
     */
    public Type getType();
    
    /**
     * Required by Comparable interface (prevents construction without type info)
     * @param o Other TypeRef to compare with
     * @return Comparison result (typically 0)
     */
    public int compareTo(TypeRef<T> o);
}

Usage Examples:

import com.jayway.jsonpath.TypeRef;
import com.jayway.jsonpath.JsonPath;
import java.util.List;
import java.util.Map;

String json = "{ \"users\": [{ \"name\": \"Alice\", \"age\": 30 }, { \"name\": \"Bob\", \"age\": 25 }] }";

// Create TypeRef for List<Map<String, Object>>
TypeRef<List<Map<String, Object>>> listTypeRef = new TypeRef<List<Map<String, Object>>>() {};

// Use with JsonPath reading
List<Map<String, Object>> users = JsonPath.read(json, "$.users", listTypeRef);

// Create TypeRef for nested generic types
TypeRef<Map<String, List<String>>> mapTypeRef = new TypeRef<Map<String, List<String>>>() {};

// TypeRef for custom classes with generics
TypeRef<List<User>> userListTypeRef = new TypeRef<List<User>>() {};

// Using with DocumentContext
DocumentContext context = JsonPath.parse(json);
List<Map<String, Object>> typedUsers = context.read("$.users", listTypeRef);

Type-Safe Reading Operations

Methods for reading JSON data with automatic type conversion to specified Java types.

// ReadContext interface methods for type-safe reading
public interface ReadContext {
    /**
     * Reads path with automatic mapping to specified class
     * @param path JsonPath expression
     * @param type Target class for mapping
     * @param filters Optional predicates for filtering
     * @return Result mapped to specified type
     */
    <T> T read(String path, Class<T> type, Predicate... filters);
    
    /**
     * Reads compiled path with automatic mapping to specified class
     * @param path Compiled JsonPath instance
     * @param type Target class for mapping
     * @return Result mapped to specified type
     */
    <T> T read(JsonPath path, Class<T> type);
    
    /**
     * Reads compiled path with generic type reference
     * @param path Compiled JsonPath instance
     * @param typeRef Type reference for generic types
     * @return Result mapped to specified generic type
     */
    <T> T read(JsonPath path, TypeRef<T> typeRef);
    
    /**
     * Reads path with generic type reference
     * @param path JsonPath expression
     * @param typeRef Type reference for generic types
     * @return Result mapped to specified generic type
     */
    <T> T read(String path, TypeRef<T> typeRef);
}

// Static methods on JsonPath class
public class JsonPath {
    /**
     * Static read with type mapping (various overloads for different input sources)
     */
    public static <T> T read(String json, String jsonPath, Class<T> type);
    public static <T> T read(Object json, String jsonPath, Class<T> type);
    public static <T> T read(File jsonFile, String jsonPath, Class<T> type) throws IOException;
    public static <T> T read(InputStream stream, String jsonPath, Class<T> type) throws IOException;
}

Usage Examples:

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.TypeRef;
import java.util.List;
import java.util.Map;

String json = "{ \"count\": 42, \"names\": [\"Alice\", \"Bob\"], \"user\": { \"name\": \"Charlie\", \"age\": 30 } }";

// Basic type-safe reading
Integer count = JsonPath.read(json, "$.count", Integer.class);
List<String> names = JsonPath.read(json, "$.names", List.class);  // Note: loses generic info

// Using TypeRef for full type safety
TypeRef<List<String>> stringListType = new TypeRef<List<String>>() {};
List<String> typedNames = JsonPath.read(json, "$.names", stringListType);

// Reading complex objects
TypeRef<Map<String, Object>> mapType = new TypeRef<Map<String, Object>>() {};
Map<String, Object> user = JsonPath.read(json, "$.user", mapType);

// With DocumentContext
DocumentContext context = JsonPath.parse(json);
Integer contextCount = context.read("$.count", Integer.class);
List<String> contextNames = context.read("$.names", stringListType);

// Custom class mapping (requires appropriate MappingProvider)
public class User {
    private String name;
    private int age;
    // constructors, getters, setters...
}

User userObject = context.read("$.user", User.class);
TypeRef<List<User>> userListType = new TypeRef<List<User>>() {};

Value Transformation

MapFunction interface for transforming values during path operations.

/**
 * Interface for transforming values during JsonPath operations
 * Used with map operations to convert values in-place
 */
public interface MapFunction {
    /**
     * Transforms the current value
     * @param currentValue The value found at the path location
     * @param configuration Configuration being used for the operation
     * @return New value to replace the current value
     */
    Object map(Object currentValue, Configuration configuration);
}

Usage Examples:

import com.jayway.jsonpath.MapFunction;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.DocumentContext;

String json = "{ \"prices\": [10.50, 15.75, 8.25], \"users\": [{ \"name\": \"alice\" }, { \"name\": \"bob\" }] }";
DocumentContext context = JsonPath.parse(json);

// Transform numeric values
MapFunction addTax = new MapFunction() {
    public Object map(Object currentValue, Configuration configuration) {
        if (currentValue instanceof Number) {
            double price = ((Number) currentValue).doubleValue();
            return price * 1.1; // Add 10% tax
        }
        return currentValue;
    }
};

// Apply transformation to all prices
context.map("$.prices[*]", addTax);

// Transform string values
MapFunction capitalizeNames = new MapFunction() {
    public Object map(Object currentValue, Configuration configuration) {
        if (currentValue instanceof String) {
            String name = (String) currentValue;
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        return currentValue;
    }
};

// Apply to user names
context.map("$.users[*].name", capitalizeNames);

// Lambda expressions (Java 8+)
context.map("$.prices[*]", (current, config) -> {
    if (current instanceof Number) {
        return ((Number) current).doubleValue() * 0.9; // 10% discount
    }
    return current;
});

// Get transformed JSON
String transformedJson = context.jsonString();

Mapping Provider Interface

SPI interface for implementing custom object mapping strategies.

/**
 * Service Provider Interface for object type mapping
 * Implementations handle conversion between JSON structures and Java objects
 */
public interface MappingProvider {
    /**
     * Maps source object to target class
     * @param source Source object to map from
     * @param targetType Target class to map to
     * @param configuration Current configuration
     * @return Mapped object of target type
     * @throws MappingException If mapping fails
     */
    <T> T map(Object source, Class<T> targetType, Configuration configuration);
    
    /**
     * Maps source object to target type using TypeRef
     * @param source Source object to map from
     * @param targetType Target type reference with generic information
     * @param configuration Current configuration
     * @return Mapped object of target type
     * @throws MappingException If mapping fails
     */
    <T> T map(Object source, TypeRef<T> targetType, Configuration configuration);
}

/**
 * Exception thrown when mapping operations fail
 */
public class MappingException extends RuntimeException {
    public MappingException(String message);
    public MappingException(String message, Throwable cause);
}

Usage Examples:

import com.jayway.jsonpath.spi.mapper.MappingProvider;
import com.jayway.jsonpath.spi.mapper.MappingException;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.TypeRef;

// Custom mapping provider implementation
public class CustomMappingProvider implements MappingProvider {
    @Override
    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {
        if (targetType == String.class && source instanceof Number) {
            return targetType.cast(source.toString());
        }
        if (targetType == Integer.class && source instanceof String) {
            try {
                return targetType.cast(Integer.parseInt((String) source));
            } catch (NumberFormatException e) {
                throw new MappingException("Cannot convert string to integer: " + source, e);
            }
        }
        // Add more custom mapping logic...
        throw new MappingException("Cannot map " + source.getClass() + " to " + targetType);
    }
    
    @Override
    public <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {
        // Handle generic type mapping
        Type type = targetType.getType();
        // Implementation depends on the specific generic type...
        throw new MappingException("Generic type mapping not implemented");
    }
}

// Use custom mapping provider
Configuration config = Configuration.builder()
    .mappingProvider(new CustomMappingProvider())
    .build();

// Now reads will use the custom mapping logic
DocumentContext context = JsonPath.using(config).parse(json);

Built-in Mapping Providers

JsonPath includes several built-in mapping providers for popular JSON libraries.

// Available mapping providers (require corresponding JSON library dependencies)

// Gson-based mapping
com.jayway.jsonpath.spi.mapper.GsonMappingProvider

// Jackson-based mapping (implicit in JacksonJsonProvider)
// Uses Jackson's ObjectMapper for type conversion

// JSON Smart mapping
com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider

// Tapestry JSON mapping
com.jayway.jsonpath.spi.mapper.TapestryMappingProvider

Usage Examples:

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.json.GsonJsonProvider;
import com.jayway.jsonpath.spi.mapper.GsonMappingProvider;
import com.jayway.jsonpath.JsonPath;

// Using Gson for both parsing and mapping
Configuration gsonConfig = Configuration.builder()
    .jsonProvider(new GsonJsonProvider())
    .mappingProvider(new GsonMappingProvider())
    .build();

// Custom objects will be mapped using Gson's capabilities
DocumentContext context = JsonPath.using(gsonConfig).parse(json);

// This will use Gson's type adapter system
User user = context.read("$.user", User.class);
List<User> users = context.read("$.users", new TypeRef<List<User>>() {});

Type Conversion Examples

Common patterns for working with different data types in JsonPath operations.

Working with Collections:

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.TypeRef;
import java.util.*;

String json = "{ \"data\": [1, 2, 3, 4, 5] }";

// Read as generic List (loses type information)
List list = JsonPath.read(json, "$.data");

// Read as typed List
TypeRef<List<Integer>> intListType = new TypeRef<List<Integer>>() {};
List<Integer> integers = JsonPath.read(json, "$.data", intListType);

// Read as Set
TypeRef<Set<Integer>> intSetType = new TypeRef<Set<Integer>>() {};
Set<Integer> integerSet = JsonPath.read(json, "$.data", intSetType);

Working with Maps:

String json = "{ \"metadata\": { \"version\": \"1.0\", \"author\": \"System\" } }";

// Read as generic Map
Map map = JsonPath.read(json, "$.metadata");

// Read as typed Map
TypeRef<Map<String, String>> stringMapType = new TypeRef<Map<String, String>>() {};
Map<String, String> metadata = JsonPath.read(json, "$.metadata", stringMapType);

Working with Custom Objects:

public class Product {
    private String name;
    private double price;
    private List<String> tags;
    // constructors, getters, setters...
}

String json = "{ \"product\": { \"name\": \"Laptop\", \"price\": 999.99, \"tags\": [\"electronics\", \"computers\"] } }";

// Direct object mapping (requires appropriate MappingProvider)
Product product = JsonPath.read(json, "$.product", Product.class);

// List of custom objects
String listJson = "{ \"products\": [{ \"name\": \"Laptop\", \"price\": 999.99 }] }";
TypeRef<List<Product>> productListType = new TypeRef<List<Product>>() {};
List<Product> products = JsonPath.read(listJson, "$.products", productListType);

Install with Tessl CLI

npx tessl i tessl/maven-com-jayway-jsonpath--json-path

docs

configuration.md

core-operations.md

document-context.md

filtering.md

index.md

type-handling.md

tile.json