JSON "tree visitor" model...

958 views
Skip to first unread message

Francis Galiegue

unread,
Apr 29, 2014, 3:42:38 PM4/29/14
to jacks...@googlegroups.com
Hello,

I have been using Jackson for a long time now and I have submitted
patches to it, some of which were blunders, I must admit.

For what it's worth, I am the developper of json-schema-validator
(https://github.com/fge/json-schema-validator) which uses jackson at
its core; and since this API is all about JSON and not POJOs, I am a
heavy user of JsonNode.

What bothers me at the moment is two things:

* JsonNode is not immutable;
* short of a JsonParser, you cannot really walk through it...

What I needed was a "tree walker", so I created one:

@Beta
public interface JsonTreeVisitor<T>
{
JsonTreeVisitResult visitNode(final JsonPointer ptr, final JsonNode node,
final ValidationMessage message)
throws JsonSchemaException;

JsonTreeVisitResult preVisitArray(final JsonPointer ptr,
final JsonNode node, final Collection<JsonPointer> children,
final ValidationMessage message)
throws JsonSchemaException;

JsonTreeVisitResult postVisitArray(final JsonPointer ptr,
final ValidationMessage message);

JsonTreeVisitResult preVisitObject(final JsonPointer ptr,
final JsonNode node, final Collection<JsonPointer> children,
final ValidationMessage message)
throws JsonSchemaException;

JsonTreeVisitResult postVisitObject(final JsonPointer ptr,
final ValidationMessage message)
throws JsonSchemaException;
}

OK, forget about ValidationMessage and JsonSchemaException, this part
is specific; the two important parts here are:

* JsonPointer: this is my own implementation of, well, JSON Pointer,
which adapts to all tree nodes but which Tatu declinded for reasons I
don't understand ;)
* Collection<JsonPointer>: this is a Collection into which the visitor
can push paths it _wants_ to be visited afterwards and no others.

But I'll be using something like this in the next version of
json-schema-validator; right now though, as annotated, it's @Beta.

Note also that it requires that the FULL TREE be available, that is,
the full JSON. With JSON Schema, you cannot reliably decide on a
success or failure before the full tree is available... As such, this
is not meant to be applied to a JsonParser.

But it may be applied in some way to Jackson; in a "waiting manner",
visitors can collect what nodes they want to visit behind the node
they are currently on (the prt argument, always present) and be only
"woken up" when needed.

An idea throw in the wild...

One last note about JsonPointer: unlike the implementation in 2.3.x,
it is independent of the TreeNode implementation! You only have to
write a TokenResolver implementation to get it to work with _any_
TreeNode implementation -- and it is overly tested.

Have fun,
--
Francis Galiegue, fgal...@gmail.com
JSON Schema in Java: http://json-schema-validator.herokuapp.com

Tatu Saloranta

unread,
Apr 29, 2014, 3:55:46 PM4/29/14
to jacks...@googlegroups.com
On Tue, Apr 29, 2014 at 12:42 PM, Francis Galiegue <fgal...@gmail.com> wrote:
Hello,

I have been using Jackson for a long time now and I have submitted
patches to it, some of which were blunders, I must admit.

For what it's worth, I am the developper of json-schema-validator
(https://github.com/fge/json-schema-validator) which uses jackson at
its core; and since this API is all about JSON and not POJOs, I am a
heavy user of JsonNode.

What bothers me at the moment is two things:

* JsonNode is not immutable;
* short of a JsonParser, you cannot really walk through it...


What do you mean by second entry? Read-only methods are exposed via JsonNode.

-+ Tatu +-

 
--
You received this message because you are subscribed to the Google Groups "jackson-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-dev...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tatu Saloranta

unread,
Apr 29, 2014, 4:05:17 PM4/29/14
to jacks...@googlegroups.com
On Tue, Apr 29, 2014 at 12:55 PM, Tatu Saloranta <tsalo...@gmail.com> wrote:
On Tue, Apr 29, 2014 at 12:42 PM, Francis Galiegue <fgal...@gmail.com> wrote:
Hello,

I have been using Jackson for a long time now and I have submitted
patches to it, some of which were blunders, I must admit.

For what it's worth, I am the developper of json-schema-validator
(https://github.com/fge/json-schema-validator) which uses jackson at
its core; and since this API is all about JSON and not POJOs, I am a
heavy user of JsonNode.

What bothers me at the moment is two things:

* JsonNode is not immutable;
* short of a JsonParser, you cannot really walk through it...


What do you mean by second entry? Read-only methods are exposed via JsonNode.

... and I am guessing comment was about TreeNode.

-+ Tatu +-

Francis Galiegue

unread,
Apr 29, 2014, 4:09:03 PM4/29/14
to jacks...@googlegroups.com
On Tue, Apr 29, 2014 at 9:55 PM, Tatu Saloranta <tsalo...@gmail.com> wrote:
[...]
>>
>> What bothers me at the moment is two things:
>>
>> * JsonNode is not immutable;
>> * short of a JsonParser, you cannot really walk through it...
>>
>
> What do you mean by second entry? Read-only methods are exposed via
> JsonNode.
>
> -+ Tatu +-
>

And so are read-write methods. I can do

if (node.isObject())
((ObjectNode) node).put("foo", "hello!");

without a problem.

The fact that I can "back cast" like that is a problem; when I get a
reference to a JsonNode, I cannot be sure that it will stay what it is
during its lifetime.

For instance, I have developed a library which does JSON Patch over
JsonNode; what I do when I have a modification to make is a
.deepCopy() of the original: I have no choice! And I am not even
guaranteed that the result will be reliable since other threads might
have altered some part of the tree while I was copying it...

JsonNode should really be immutable!

Jeff Schnitzer

unread,
Apr 29, 2014, 4:13:18 PM4/29/14
to jacks...@googlegroups.com
While I love immutable objects too, it's really hard to work with
large object graphs that are immutable. For example, adding a node
down at the end of a very long branch requires the entire upstream
tree to be regenerated. In the end, your code looks like Clojure,
which some people like, but most do not.

Jeff

Tatu Saloranta

unread,
Apr 29, 2014, 4:34:25 PM4/29/14
to jacks...@googlegroups.com
On Tue, Apr 29, 2014 at 1:09 PM, Francis Galiegue <fgal...@gmail.com> wrote:
On Tue, Apr 29, 2014 at 9:55 PM, Tatu Saloranta <tsalo...@gmail.com> wrote:
[...]
>>
>> What bothers me at the moment is two things:
>>
>> * JsonNode is not immutable;
>> * short of a JsonParser, you cannot really walk through it...
>>
>
> What do you mean by second entry? Read-only methods are exposed via
> JsonNode.
>
> -+ Tatu +-
>

And so are read-write methods. I can do

if (node.isObject())
    ((ObjectNode) node).put("foo", "hello!");

without a problem.


No, this is not same at all.

JsonNode has "fields()" and "fieldNames()" methods, as well as type accessors. So you can traverse contents without upcasting.

 
The fact that I can "back cast" like that is a problem; when I get a
reference to a JsonNode, I cannot be sure that it will stay what it is
during its lifetime.

For instance, I have developed a library which does JSON Patch over
JsonNode; what I do when I have a modification to make is a
.deepCopy() of the original: I have no choice! And I am not even
guaranteed that the result will be reliable since other threads might
have altered some part of the tree while I was copying it...

JsonNode should really be immutable!


We have gone over this multiple times. You think it should be immutable.
This is an opinion, not a fact.

I agree that it would be great to have AN IMMUTABLE tree implementation.
But JsonNode will never be immutable, for multiple practical reasons.
I have yet to see a single viable proposal for a tree that supports both immutable use case (read-only), and ability to modify JSON, either via modes, or truly immutable functional approaches.

I am getting tired of talking around in circles here,

-+ Tatu +-

 
--
Francis Galiegue, fgal...@gmail.com
JSON Schema in Java: http://json-schema-validator.herokuapp.com

Tatu Saloranta

unread,
Apr 29, 2014, 4:35:43 PM4/29/14
to jacks...@googlegroups.com
Exactly.

And let me just state that I would really, REALLY like to see a viable proposal for some form of immutable JSON trees; ideally plugged as TreeNode/TreeCodec. Question of what to do with legacy JsonNode is something that would follow up, and not pre-date new versions.

-+ Tatu +-

Francis Galiegue

unread,
Apr 29, 2014, 4:42:16 PM4/29/14
to jacks...@googlegroups.com
On Tue, Apr 29, 2014 at 10:13 PM, Jeff Schnitzer <je...@infohazard.org> wrote:
> While I love immutable objects too, it's really hard to work with
> large object graphs that are immutable. For example, adding a node
> down at the end of a very long branch requires the entire upstream
> tree to be regenerated. In the end, your code looks like Clojure,
> which some people like, but most do not.
>

Sorry to contradict you, but you don't need clojure to do that. Not at all...

I can program you a tree model which is "deeply immutable" but "deeply
mutable on demand" any day. No need for Clojure; plain Java can do it
easily.

Francis Galiegue

unread,
Apr 29, 2014, 4:50:49 PM4/29/14
to jacks...@googlegroups.com
On Tue, Apr 29, 2014 at 10:34 PM, Tatu Saloranta <tsalo...@gmail.com> wrote:
[...]
>>
>> And so are read-write methods. I can do
>>
>> if (node.isObject())
>> ((ObjectNode) node).put("foo", "hello!");
>>
>> without a problem.
>>
>
> No, this is not same at all.
>
> JsonNode has "fields()" and "fieldNames()" methods, as well as type
> accessors. So you can traverse contents without upcasting.
>

Yes. But if it happens that node.isObject() is true then a simple cast
will grant me basically "root access". You cannot deny that!

[...]
>>
>> JsonNode should really be immutable!
>>
>
> We have gone over this multiple times. You think it should be immutable.
> This is an opinion, not a fact.
>
> I agree that it would be great to have AN IMMUTABLE tree implementation.
> But JsonNode will never be immutable, for multiple practical reasons.
> I have yet to see a single viable proposal for a tree that supports both
> immutable use case (read-only), and ability to modify JSON, either via
> modes, or truly immutable functional approaches.
>
> I am getting tired of talking around in circles here,
>

And so am I to be honest. A JsonNode has a name, it is supposed to
represent JSON. Nothing else. The fact that POJONode exists, for
example, is, well, a problem: RFC 4627 did not define that, nor does
RFC 7159. BinaryNode suffers the same problem.

JsonNode represents JSON reliably, except for those two aspects which
are: 1. it is mutable (you read a JSON Text into a JsonNode, it may be
altered, it won't be the same JSON Text anymore), 2. it can be
subclassed to represent non JSON values (POJO, and binary even though
binary is just a Base64-encoded string).

This is not what JSON is! Plain and simple! And yet I can't do but use
Jackson; no other JSON library in Java allows as good traversal
possibilities as JsonNode does, nothing else than JsonNode can
seamlessly coerce JSON values to sane representations.

The only thing it really lacks is immutability!

Jeff Schnitzer

unread,
Apr 29, 2014, 5:20:21 PM4/29/14
to jacks...@googlegroups.com
I will assume this is language issue and you are not a native speaker
of English.

In English, the two statements "your code looks like Clojure" and
"your code requires Clojure" have very different meanings. "Code that
looks like Clojure" could be code written in any language (including,
in this case, Java) that follows the pure-functional idioms and
patterns that naturally fit in Clojure.

Now, please reread what I said.

Jeff

Francis Galiegue

unread,
Apr 29, 2014, 6:10:19 PM4/29/14
to jacks...@googlegroups.com
On Tue, Apr 29, 2014 at 11:20 PM, Jeff Schnitzer <je...@infohazard.org> wrote:
> I will assume this is language issue and you are not a native speaker
> of English.
>
> In English, the two statements "your code looks like Clojure" and
> "your code requires Clojure" have very different meanings. "Code that
> looks like Clojure" could be code written in any language (including,
> in this case, Java) that follows the pure-functional idioms and
> patterns that naturally fit in Clojure.
>
> Now, please reread what I said.
>

Well I just did like you instructed and, uhm, what is your point?

I am fully aware that Java is not Clojure and honestly, I don't care.
I can do what I want with Java anyway. So... Again, your point is...?
Reply all
Reply to author
Forward
0 new messages