Serialization problem - Maximum allowed depth has been exceeded

476 views
Skip to first unread message

thorste...@gmail.com

unread,
Oct 26, 2010, 6:52:22 AM10/26/10
to Jayrock
Hello,

if I want to serialize a large hierarchical object from .NET to JSON,
I get the following error:
[Exception: Maximum allowed depth has been exceeded.]

I did a test with the .NET BinaryFormatter which is able to serialize
the same object without any errors.

Is this a bug in the Jayrock framework that can be fixed?

Regards,
Thorsten

Atif Aziz

unread,
Oct 26, 2010, 9:16:02 AM10/26/10
to jay...@googlegroups.com
This is not a bug. There's a property on JsonReader called MaxDepth that control the maximum allowed depth:
 
By default, the max depth is around 100, which is already very high! I'm assuming you have a hierarchy deeper than that? If you don't want to be restricted then you can set MaxDepth to int.MaxValue.
 
- Atif

--
You received this message because you are subscribed to the Google Groups "Jayrock" group.
To post to this group, send email to jay...@googlegroups.com.
To unsubscribe from this group, send email to jayrock+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/jayrock?hl=en.


thorste...@gmail.com

unread,
Oct 27, 2010, 2:11:16 AM10/27/10
to Jayrock
Hello Atif,

thanks for your answer. Everytime when I run in such a problem I am
fascinated how flexible you designed this framework! Really great.
Can you please tell me what's the best way to set the MaxDepth
property in my software?

Regards,
Thorsten

On 26 Okt., 15:16, Atif Aziz <aziza...@gmail.com> wrote:
> This is not a bug. There's a property on JsonReader called MaxDepth that
> control the maximum allowed depth:http://code.google.com/p/jayrock/source/browse/trunk/src/Jayrock.Json...
>
> By default, the max depth is around 100, which is already very high! I'm
> assuming you have a hierarchy deeper than that? If you don't want to be
> restricted then you can set MaxDepth to int.MaxValue.
>
> - Atif
> On Tue, Oct 26, 2010 at 12:52 PM, thorsten.kr...@gmail.com <
>
> thorsten.kr...@gmail.com> wrote:
> > Hello,
>
> > if I want to serialize a large hierarchical object from .NET to JSON,
> > I get the following error:
> > [Exception: Maximum allowed depth has been exceeded.]
>
> > I did a test with the .NET BinaryFormatter which is able to serialize
> > the same object without any errors.
>
> > Is this a bug in the Jayrock framework that can be fixed?
>
> > Regards,
> > Thorsten
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Jayrock" group.
> > To post to this group, send email to jay...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > jayrock+u...@googlegroups.com<jayrock%2Bunsu...@googlegroups.com>
> > .

Atif Aziz

unread,
Oct 27, 2010, 7:07:12 AM10/27/10
to jay...@googlegroups.com
Can you please tell me what's the best way to set the MaxDepth property in my software?
 
It would be right after you create a JsonReader instance through, for example, JsonText.CreateReader. Do you have a more complciated scenario where you don't have control over where and when a JsonReader is created?
 
- Atif

To unsubscribe from this group, send email to jayrock+u...@googlegroups.com.

thorste...@gmail.com

unread,
Oct 27, 2010, 7:20:38 AM10/27/10
to Jayrock
I do not manually create an instance of JsonReader. The exception is
thrown by a JsonRpcHandler which has to serialize the .NET object for
my JSON-RPC endpoint...

On 27 Okt., 13:07, Atif Aziz <aziza...@gmail.com> wrote:
> > Can you please tell me what's the best way to set the MaxDepth property in
> > my software?
>
> It would be right after you create a JsonReader instance through, for
> example, JsonText.CreateReader. Do you have a more complciated scenario
> where you don't have control over where and when a JsonReader is created?
>
> - Atif
>
> On Wed, Oct 27, 2010 at 8:11 AM, thorsten.kr...@gmail.com <
> > <jayrock%2Bunsu...@googlegroups.com<jayrock%252Buns...@googlegroups.com>

thorste...@gmail.com

unread,
Nov 4, 2010, 5:06:13 AM11/4/10
to Jayrock
Is there any way to solve this case?

Regards Thorsten

On 27 Okt., 12:20, "thorsten.kr...@gmail.com"

Atif Aziz

unread,
Nov 4, 2010, 6:07:05 AM11/4/10
to jay...@googlegroups.com
Oops, I replied but never sent the post. It was still sitting in my drafts. :P Will send it out right away.

- Atif

> To unsubscribe from this group, send email to jayrock+u...@googlegroups.com.

Atif Aziz

unread,
Nov 4, 2010, 6:07:13 AM11/4/10
to jay...@googlegroups.com
Whenever Jayrock creates a reader for JSON text, it calls JsonText.CreateReader to do so and user code is encouraged to do the same. The JsonReader instance returned by JsonText.CreateReader can be customized by suppliying your own factory method. Here's an example of how to do this:
 
var rf = JsonText.CurrentReaderFactory;
JsonText.CurrentReaderFactory = (r, o) => {
  var reader = rf(r, o);
  reader.MaxDepth = 5;
  return reader;
};
 
You'll notice that the above sets the MaxDepth to a very low number (5) but I've done this intentionally and only for demonstration purposes. You'll probably want to set it to something more suitable in your case (which seems to be greater than the default of 100) or even read it from configuration. Now the following reading will throw an exception saying that the maximum allowed depth has been exceeded:
 
JsonText.CreateReader(
 @"[1,[2,[3,[4,[5,[6,[7,[8,[9]]]]]]]]]").Skip();
 
The call to Skip method skips over the entire value at the root, effectively reading through all the nested arrays and eventually breaks when reaching a depth of 6.
This line first captures the existing factory, which is presumably the default one supplied by Jayrock and simply returns an instance of JsonTextReader:
 
var rf = JsonText.CurrentReaderFactory;
 
Inside the new factory method, we still ask the original factory to create the JsonReader instance but then customize the MaxDepth just prior to returning it.

JsonText.CurrentReaderFactory = (r, o) => {
  var reader = rf(r, o);
  reader.MaxDepth = 5;
  return reader;
};

- Atif
 
To unsubscribe from this group, send email to jayrock+u...@googlegroups.com.

Neil Cawse

unread,
Dec 22, 2010, 10:03:56 AM12/22/10
to jay...@googlegroups.com, aziz...@gmail.com

Aziz, thanks again for your hardwork on Jayrock. Couple of things we have picked up – we made the following changes to the importer code to make it work correctly with List<T>:

 

 

        static IImporter FindCompatibleImporter(Type type)

        {

            Debug.Assert(type != null);

 

            if (typeof(IJsonImportable).IsAssignableFrom(type))

                return new ImportAwareImporter(type);

           

            if (type.IsArray && type.GetArrayRank() == 1)

                return new ArrayImporter(type);

 

            if (type.IsEnum)

                return new EnumImporter(type);

 

            #if !NET_1_0 && !NET_1_1

 

            if (Reflector.IsConstructionOfNullable(type))

                return new NullableImporter(type);

 

            bool isGenericList = Reflector.IsConstructionOfGenericTypeDefinition(type, typeof(IList<>));

            bool isGenericCollection = !isGenericList && Reflector.IsConstructionOfGenericTypeDefinition(type, typeof(ICollection<>));

            bool isSequence = (!isGenericCollection && !isGenericList) && (type == typeof(IEnumerable) || Reflector.IsConstructionOfGenericTypeDefinition(type, typeof(IEnumerable<>)));

 

 

also in the reflector class:

 

        internal static bool IsConstructionOfGenericTypeDefinition(Type type, Type genericTypeDefinition)

        {

            if (type == null) throw new ArgumentNullException("type");

            if (genericTypeDefinition == null) throw new ArgumentNullException("genericTypeDefinition");

 

            if (!genericTypeDefinition.IsGenericTypeDefinition)

                throw new ArgumentException(string.Format("{0} is not a generic type definition.", genericTypeDefinition), "genericTypeDefinition");

 

            while (type != null && type != typeof(object))

            {

                Type cur = type.IsGenericType ? type.GetGenericTypeDefinition() : type;

                if (genericTypeDefinition == cur || Array.Find(cur.GetInterfaces(), delegate(Type t) { return (t.IsGenericType ? t.GetGenericTypeDefinition() : t) == genericTypeDefinition; }) != null)

                {

                    return true;

                }

 

                type = type.BaseType;

            }

            return false;

        }

 

Reply all
Reply to author
Forward
0 new messages