blob: c9062aacf415754d20eaae5e92d4e5e6880461d7 [file] [log] [blame]
<!--
/***************************************************************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
***************************************************************************************************************************/
-->
Non-Tree Models and Recursion Detection
<p>
The Juneau Serializer API is designed to be used against POJO tree structures.
It expects that there not be loops in the POJO model (e.g. children with references to parents, etc...).
If you try to serialize models with loops, you will usually cause a <c>StackOverflowError</c> to
be thrown (if {@link oaj.BeanTraverseContext#BEANTRAVERSE_maxDepth} is not reached
first).
</p>
<p>
If you still want to use the Juneau serializers on such models, Juneau provides the
{@link oaj.BeanTraverseContext#BEANTRAVERSE_detectRecursions} setting.
It tells the serializer to look for instances of an object in the current branch of the tree and skip
serialization when a duplicate is encountered.
</p>
<p>
For example, let's make a POJO model out of the following classes:
</p>
<p class='bpcode w800'>
<jk>public class</jk> A {
<jk>public</jk> B b;
}
<jk>public class</jk> B {
<jk>public</jk> C c;
}
<jk>public class</jk> C {
<jk>public</jk> A a;
}
</p>
<p>
Now we create a model with a loop and serialize the results.
</p>
<p class='bpcode w800'>
<jc>// Clone an existing serializer and set property for detecting recursions.</jc>
JsonSerializer s = SimpleJsonSerializer.<jsf>DEFAULT_READABLE</jsf>.builder().detectRecursions(<jk>true</jk>).build();
<jc>// Create a recursive loop.</jc>
A a = <jk>new</jk> A();
a.<jf>b</jf> = <jk>new</jk> B();
a.<jf>b</jf>.<jf>c</jf> = <jk>new</jk> C();
a.<jf>b</jf>.<jf>c</jf>.<jf>a</jf> = a;
<jc>// Serialize to JSON.</jc>
String json = s.serialize(a);
</p>
<p>
What we end up with is the following, which does not serialize the contents of the <c>c</c> field:
</p>
<p class='bpcode w800'>
{
<jok>b</jok>: {
<jok>c</jok>: {
}
}
}
</p>
<p>
Without recursion detection enabled, this would cause a stack-overflow error.
</p>
<p>
Recursion detection introduces a performance penalty of around 20%.
For this reason the setting is disabled by default.
</p>