cd7e02dd6575c86846318e3d0c62c5815e46cea7
[platform/upstream/dotnet/runtime.git] /
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System.Diagnostics;
6
7 namespace System.Text.Json.Serialization
8 {
9     public static partial class JsonSerializer
10     {
11         private static void HandleStartObject(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
12         {
13             if (state.Current.Skip())
14             {
15                 state.Push();
16                 state.Current.Drain = true;
17                 return;
18             }
19
20             if (state.Current.IsProcessingEnumerable)
21             {
22                 Type objType = state.Current.GetElementType();
23                 state.Push();
24                 state.Current.Initialize(objType, options);
25             }
26             else if (state.Current.JsonPropertyInfo != null)
27             {
28                 if (state.Current.IsDictionary)
29                 {
30                     // Verify that the Dictionary can be deserialized by having <string> as first generic argument.
31                     Debug.Assert(state.Current.JsonClassInfo.Type.GetGenericArguments().Length >= 1);
32                     if (state.Current.JsonClassInfo.Type.GetGenericArguments()[0].UnderlyingSystemType != typeof(string))
33                     {
34                         ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonClassInfo.Type, reader, state.PropertyPath);
35                     }
36
37                     ClassType classType = state.Current.JsonClassInfo.ElementClassInfo.ClassType;
38
39                     if (state.Current.ReturnValue == null)
40                     {
41                         // The Dictionary created below will be returned to corresponding Parse() etc method.
42                         // Ensure any nested array creates a new frame.
43                         state.Current.EnumerableCreated = true;
44                     }
45                     else
46                     {
47                         Debug.Assert(classType == ClassType.Object || classType == ClassType.Dictionary);
48
49                         // A nested object or dictionary.
50                         JsonClassInfo classInfoTemp = state.Current.JsonClassInfo;
51                         state.Push();
52                         state.Current.JsonClassInfo = classInfoTemp.ElementClassInfo;
53                         state.Current.InitializeJsonPropertyInfo();
54                     }
55                 }
56                 else
57                 {
58                     // Nested object.
59                     Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
60                     state.Push();
61                     state.Current.Initialize(objType, options);
62                 }
63             }
64
65             JsonClassInfo classInfo = state.Current.JsonClassInfo;
66             state.Current.ReturnValue = classInfo.CreateObject();
67         }
68
69         private static bool HandleEndObject(JsonSerializerOptions options, ref ReadStack state, ref Utf8JsonReader reader)
70         {
71             bool isLastFrame = state.IsLastFrame;
72             if (state.Current.Drain)
73             {
74                 state.Pop();
75                 return isLastFrame;
76             }
77
78             state.Current.JsonClassInfo.UpdateSortedPropertyCache(ref state.Current);
79
80             object value = state.Current.ReturnValue;
81
82             if (isLastFrame)
83             {
84                 state.Current.Reset();
85                 state.Current.ReturnValue = value;
86                 return true;
87             }
88
89             state.Pop();
90             ApplyObjectToEnumerable(value, options, ref state, ref reader);
91             return false;
92         }
93     }
94 }