-
Notifications
You must be signed in to change notification settings - Fork 310
💡 Suggestion: small integration points for SJF4J (JSON-oriented handling) #1108
Description
Hi, I’m the author of SJF4J (Simple JSON Facade for Java).
After reading adk-java, I think SJF4J could be useful in a few narrow, concrete places.
This is not about replacing Jackson, but about improving places where ADK already operates on mutable nested Map/List/value graphs.
1. State / stateDelta
State and EventActions.stateDelta() are already very close to a JSON-like object model:
Map<String, Object>state- nested
Map/Listvalues - a separate delta
- custom handling for removal
Relevant code:
sessions/State.javaevents/EventActions.javasessions/InMemorySessionService.java
Today:
- deep updates rely on manual merge logic
- deletions use a sentinel
- changes are tracked as a flat map
For nested state, this becomes harder to reason about and replay.
A patch-based approach makes the transition explicit:
Map<String, Object> previous = oldSession.state();
Map<String, Object> next = newState;
JsonPatch patch = JsonPatch.diff(previous, next);
patch.apply(session.state());This would:
- remove the need for custom deep-merge logic (already present in
EventActions.Builder.merge()) - avoid sentinel-based delete semantics
- make state transitions explicit and replayable
2. SchemaUtils
SchemaUtils currently does lightweight recursive validation (required + basic type checks).
This works, but it cannot express common constraints:
Map<String, Object> args = Map.of(
"city", "",
"days", -1
);This is type-correct but still semantically invalid.
With JSON Schema:
{
"type": "object",
"properties": {
"city": { "type": "string", "minLength": 1 },
"days": { "type": "integer", "minimum": 1 }
},
"required": ["city", "days"]
}SJF4J supports:
minLength,minimum,enumoneOf/ polymorphic inputsadditionalProperties- full Draft 2020-12 validation
This could strengthen validation for:
- tool args
- structured outputs
- configs
- session payloads
3. zjsonpatch usage
In LlmRequestComparator, the current flow is roughly:
object → JSON string → JsonNode → diff
Using a native object-graph diff avoids that round trip:
JsonPatch patch = JsonPatch.diff(recorded, current);Potential benefits:
- no intermediate
JsonNode - one less dependency
- works directly on existing
Map/Liststructures
4. YAML handling
There are multiple YAML-specific paths today:
ConfigAgentUtilsYamlPreprocessorRecordingsLoader
SJF4J can unify YAML and JSON into the same structural model:
@NodeNaming(NamingStrategy.SNAKE_CASE)
public class RootAgentConfig extends JsonObject {}
RootAgentConfig config = Sjf4j.fromYaml(yamlText, RootAgentConfig.class);
new SchemaValidator().requireValid(config);This allows:
- consistent handling of YAML / JSON / in-memory state
- shared path access / patch / validation
- simpler snake_case mapping
🎯 Summary
Potential integration points:
State→ patch-based state transitionsSchemaUtils→ full JSON Schema validationzjsonpatch→ direct object diff- YAML → unified structural model
All of these are local improvements, not architectural changes.
🙏
SJF4J is still evolving and not yet as mature as long-established libraries.
I’ll continue improving it and keeping it stable.
If any of these directions are interesting, I’d be happy to help and follow up on this.
Thanks again for the great project 👍