-
Notifications
You must be signed in to change notification settings - Fork 10
json layer
Verdict: three independent JSON concerns. (1) JSON-RPC envelope — hand-rolled Jackson 3 streaming, raw-value passthrough. (2) User payloads — PayloadSerializer/Deserializer (Jackson default, kotlinx option). (3) Schemas/documents — library-neutral JsonDocument/JsonSchema in api, factories discovered by ServiceLoader keyed on source type.
JsonRpcCodec tachyon-core/src/main/java/dev/tachyonmcp/core/transport/jsonrpc/JsonRpcCodec.java:
-
JsonUtils.toParamsNode(Object)narrows a rawparamspayload (tree, or a decodedMap) to oneObjectNode; anything else (absent, by-position array) ⇒ empty object, so a validator's field lookups just miss instead of branching on Java typeJsonUtils#toParamsNode. -
parseRequest(ByteBuf)streaming;paramsread as Jackson tree (JsonNode),result/error.datakept raw JSON string JsonRpcCodec#parseRequest, JsonRpcCodec. - Classification priority: error (code+message) > result > method+id ⇒
Request> method ⇒ JsonRpcMessage.Notification > IAE JsonRpcCodec#parseRequest. -
id: long / double / string / null JsonRpcCodec#parseId → RequestId (tachyon-api/.../server/domain/RequestId.java). - Serialize to
byte[](GC-managed, not pooled — dropped response on shutdown ≠ leak) JsonRpcCodec#serialize. -
JsonRpcMessage sealed
Request<T> | Response | Error | Notification<T>JsonRpcMessage.JsonRpcError(code, message, data, httpStatus=200)JsonRpcError. -
ValueSerializer plain Map/List/scalar writer (unknown ⇒
toString()) ValueSerializer#writeJsonValue.
| Type | Proof |
|---|---|
JsonDocument — json(), unwrap(Class), of(String) (no validation), parse, from(source, type)
|
JsonDocument |
JsonObject / JsonArray typed accessors (stringOpt, intOpt exact, …) |
JsonObject |
JsonSchema (unchecked, generate(Class)) |
JsonSchema.java |
JsonSchemaValidator + noop()
|
JsonSchemaValidator |
SPI JsonDocumentFactory<T> / JsonSchemaFactory<T> (sourceType, priority) |
json/spi/*.java |
ServiceLoader registrations:
| Services file | Impls |
|---|---|
core ...JsonDocumentFactory
|
Jackson3JsonFactory(String), JacksonNodeJsonFactory, JacksonObjectJsonFactory
|
core ...JsonSchemaFactory
|
above 3 + KtSchemaResourceFactory(Class, prio 0), JavaTypeSchemaFactory(Class, prio 1000), MapJsonFactory(Map) |
| kotlin |
KotlinxJsonElementFactory, KotlinxJsonObjectFactory
|
| kt-schema |
KtSchemaReflectionFactory (Class, prio 10; declines on generator failure, e.g. Java record with int) |
JsonSchema.generate(Class) chain = codegen resource → kt-schema reflection → Java reflection. JavaTypeSchemas covers records (required unless Optional/JSpecify @Nullable), POJOs (public getters/fields, only primitives required), enums, arrays/collections, maps (additionalProperties), java.time/UUID/URI formats; cycles ⇒ bare object. Factory declines non-object types so chain still fails for them JavaTypeSchemaFactory#priority.
Server requires exactly one String-source JsonSchemaFactory else ISE DefaultTachyonServer#discoverSchemaFactory; used to validate tool schema roots at registration JsonSchemaUtils#parseSchemaRoot.
KtSchemaResourceFactory looks up META-INF/kt-schema/schemas/<fqcn path>.json on context classloader (build-time generated) KtSchemaResourceFactory#sourceType.
- Default input and output validator
NetworkntJsonSchemaValidator, dialect 2020-12, compiled-schema cache keyed by schema JSON stringNetworkntJsonSchemaValidator. - Override via
json { inputSchemaValidator / outputSchemaValidator / schemaValidator }JsonConfig. Output validatornoop()skips output checkToolsCallHandler#validateOutput. - Registration rules (
JsonSchemaUtils): input root must betype: objectJsonSchemaUtils#validateInputSchemaRoot; output must be objectJsonSchemaUtils#validateOutputSchemaRoot;x-mcp-headerrulesJsonSchemaUtils→ protocol-versions.
- Default
JacksonPayloadSerdeover sharedJsonUtils.mapper()(Duration deserialized from millis)JacksonPayloadSerde,JsonUtils#MAPPER. -
ToolRequest.arguments()=Args(wraps JSON;decode(Class)via deserializer carried on request)tachyon-api/.../server/domain/Args.java. - Structured results serialized to
JsonDocumentbefore mappingJsonUtils.serializeStructuredJsonDocument. - Kotlin:
KxSerializationSerde→ tachyon-kotlin.
tools.jackson.*): JsonNode.isString()/stringValue()/asString(), properties() — not Jackson 2 names.
Related: feature-registries, errors.
📄 source .llm-wiki/concepts/json-layer.md · updated 2026-09-17 · verified at 1a4081f4 · tags [concept, json, schema]
🧭 Start
⚙️ Concepts (cross-cutting)
- request-lifecycle
- netty-pipeline
- protocol-versions
- sessions
- sse-streams
- feature-registries
- tasks
- extensions
- json-layer
- errors
- concurrency
- declarative-configuration
- configuration
- security-guards
- observability
- api-stability
📦 Modules