json-path/JsonPath · error · JsonPathException

Not a JSON Node

Error message

Not a JSON Node

What it means

JacksonJsonNodeJsonProvider.toJson throws JsonPathException("Not a JSON Node") when the object passed for serialization is not a Jackson JsonNode instance. This provider can only serialize tree-model values; unlike JacksonJsonProvider it does not serialize arbitrary POJOs.

Source

Thrown at json-path/src/main/java/com/jayway/jsonpath/spi/json/JacksonJsonNodeJsonProvider.java:80

            return objectMapper.readTree(json);
        } catch (IOException e) {
            throw new InvalidJsonException(e, new String(json, StandardCharsets.UTF_8));
        }
    }

    @Override
    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {
        try {
            return objectMapper.readTree(new InputStreamReader(jsonStream, charset));
        } catch (IOException e) {
            throw new InvalidJsonException(e);
        }
    }

    @Override
    public String toJson(Object obj) {
        if (!(obj instanceof JsonNode)) {
            throw new JsonPathException("Not a JSON Node");
        }
        return obj.toString();
    }

    @Override
    public Object createArray() {
        return JsonNodeFactory.instance.arrayNode();
    }

    @Override
    public Object createMap() {
        return JsonNodeFactory.instance.objectNode();
    }

    public Object unwrap(Object o) {
        if (o == null) {
            return null;
        }

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Ensure the object is a com.fasterxml.jackson.databind.JsonNode; convert Maps/Lists with objectMapper.valueToTree(obj) first
  2. Use JacksonJsonProvider instead if you need POJO serialization
  3. Make provider selection and usage consistent in a single Configuration object shared across parse/read/toJson calls
  4. Add an instanceof check in your own code before calling toJson

Example fix

// before
String json = nodeProvider.toJson(myMap);
// after
JsonNode node = objectMapper.valueToTree(myMap);
String json = nodeProvider.toJson(node);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(obj instanceof JsonNode)) {
    obj = objectMapper.valueToTree(obj); // convert before calling toJson
}

Type guard

static boolean isJsonNode(Object o) {
    return o instanceof com.fasterxml.jackson.databind.JsonNode;
}

Try / catch

try {
    String json = nodeProvider.toJson(obj);
} catch (JsonPathException e) {
    if (e.getMessage().contains("Not a JSON Node")) {
        json = nodeProvider.toJson(objectMapper.valueToTree(obj));
    } else throw e;
}

Prevention

When it happens

Trigger: Calling toJson(obj) (or JsonPath.toJson / operations that serialize mapped results) with a Map, List, POJO, or parsed value obtained from a different provider (e.g. JacksonJsonProvider or GsonJsonProvider) while Configuration uses JacksonJsonNodeJsonProvider.

Common situations: Mixing providers: parsing with the default provider but serializing via the JsonNode provider; upgrading code from JacksonJsonProvider to JacksonJsonNodeJsonProvider and assuming toJson accepts POJOs; passing DocumentContext results (Maps/Lists) to this provider's toJson.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11). Data as JSON: /api/errors/f2e84cea2402333c. Report an issue: GitHub.