| <!-- |
| /*************************************************************************************************************************** |
| * 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> |