private static bool WriteObject( JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { JsonClassInfo classInfo = state.Current.JsonClassInfo; // Write the start. if (!state.Current.StartObjectWritten) { state.Current.WriteObjectOrArrayStart(ClassType.Object, writer); } // Determine if we are done enumerating properties. if (state.Current.PropertyIndex != classInfo.PropertyCount) { HandleObject(options, writer, ref state); return(false); } writer.WriteEndObject(); if (state.Current.PopStackOnEndObject) { state.Pop(); } else { state.Current.EndObject(); } return(true); }
private static bool HandleEnumerable( JsonClassInfo elementClassInfo, JsonSerializerOptions options, ref Utf8JsonWriter writer, ref WriteStack state) { Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable); JsonPropertyInfo propertyInfo = state.Current.JsonPropertyInfo; if (state.Current.Enumerator == null) { if (propertyInfo._name == null) { writer.WriteStartArray(); } else { writer.WriteStartArray(propertyInfo._name); } IEnumerable enumerable = (IEnumerable)propertyInfo.GetValueAsObject(state.Current.CurrentValue, options); if (enumerable != null) { state.Current.Enumerator = enumerable.GetEnumerator(); } } if (state.Current.Enumerator != null && state.Current.Enumerator.MoveNext()) { if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.GetPolicyProperty().WriteEnumerable(options, ref state.Current, ref writer); } else { // An object or another enumerator requires a new stack frame JsonClassInfo nextClassInfo = propertyInfo.ElementClassInfo; object nextValue = state.Current.Enumerator.Current; state.Push(nextClassInfo, nextValue); } return(false); } // We are done enumerating. writer.WriteEndArray(); if (state.Current.PopStackOnEndArray) { state.Pop(); } else { state.Current.EndArray(); } return(true); }
private static bool WriteObject( JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { // Write the start. if (!state.Current.StartObjectWritten) { state.Current.WriteObjectOrArrayStart(ClassType.Object, writer); } // Determine if we are done enumerating properties. // If the ClassType is unknown, there will be a policy property applied. There is probably // a better way to identify policy properties- maybe not put them in the normal property bag? JsonClassInfo classInfo = state.Current.JsonClassInfo; if (classInfo.ClassType != ClassType.Unknown && state.Current.PropertyIndex != classInfo.PropertyCount) { HandleObject(options, writer, ref state); return(false); } writer.WriteEndObject(); if (state.Current.PopStackOnEndObject) { state.Pop(); } else { state.Current.EndObject(); } return(true); }
internal bool TryWriteDataExtensionProperty(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state) { Debug.Assert(value != null); if (!IsInternalConverter) { return(TryWrite(writer, value, options, ref state)); } Debug.Assert(this is JsonDictionaryConverter <T>); state.Current.PolymorphicJsonPropertyInfo = state.Current.DeclaredJsonPropertyInfo !.RuntimeClassInfo.ElementClassInfo !.PropertyInfoForClassInfo; if (writer.CurrentDepth >= options.EffectiveMaxDepth) { ThrowHelper.ThrowJsonException_SerializerCycleDetected(options.EffectiveMaxDepth); } JsonDictionaryConverter <T> dictionaryConverter = (JsonDictionaryConverter <T>) this; bool isContinuation = state.IsContinuation; bool success; state.Push(); if (!isContinuation) { Debug.Assert(state.Current.OriginalDepth == 0); state.Current.OriginalDepth = writer.CurrentDepth; } // Ignore the naming policy for extension data. state.Current.IgnoreDictionaryKeyPolicy = true; success = dictionaryConverter.OnWriteResume(writer, value, options, ref state); if (success) { VerifyWrite(state.Current.OriginalDepth, writer); } state.Pop(success); return(success); }
private static bool WriteObject( JsonSerializerOptions options, ref Utf8JsonWriter writer, ref WriteStack state) { JsonClassInfo classInfo = state.Current.JsonClassInfo; // Write the start. if (!state.Current.StartObjectWritten) { if (state.Current.JsonPropertyInfo?._escapedName == null) { writer.WriteStartObject(); } else { writer.WriteStartObject(state.Current.JsonPropertyInfo._escapedName); } state.Current.StartObjectWritten = true; } // Determine if we are done enumerating properties. if (state.Current.PropertyIndex != classInfo.PropertyCount) { HandleObject(options, ref writer, ref state); return(false); } writer.WriteEndObject(); if (state.Current.PopStackOnEndObject) { state.Pop(); } else { state.Current.EndObject(); } return(true); }
private static bool HandleEnumerable( JsonClassInfo elementClassInfo, JsonSerializerOptions options, ref Utf8JsonWriter writer, ref WriteStack state) { Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable); JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (state.Current.Enumerator == null) { if (jsonPropertyInfo._name == null) { writer.WriteStartArray(); } else { writer.WriteStartArray(jsonPropertyInfo._name); } IEnumerable enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue, options); if (enumerable != null) { state.Current.Enumerator = enumerable.GetEnumerator(); } } if (state.Current.Enumerator != null && state.Current.Enumerator.MoveNext()) { // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { object currentValue = state.Current.Enumerator.Current; GetRuntimeClassInfo(currentValue, ref elementClassInfo, options); } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.GetPolicyProperty().WriteEnumerable(options, ref state.Current, ref writer); } else if (state.Current.Enumerator.Current == null) { // Write a null object or enumerable. writer.WriteNullValue(); } else { // An object or another enumerator requires a new stack frame. object nextValue = state.Current.Enumerator.Current; state.Push(elementClassInfo, nextValue); } return(false); } // We are done enumerating. writer.WriteEndArray(); if (state.Current.PopStackOnEndArray) { state.Pop(); } else { state.Current.EndArray(); } return(true); }
internal bool TryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state) { if (writer.CurrentDepth >= options.EffectiveMaxDepth) { ThrowHelper.ThrowJsonException_SerializerCycleDetected(options.EffectiveMaxDepth); } if (CanBePolymorphic) { if (value == null) { if (!HandleNull) { writer.WriteNullValue(); } else { Debug.Assert(ClassType == ClassType.Value); Debug.Assert(!state.IsContinuation); int originalPropertyDepth = writer.CurrentDepth; Write(writer, value, options); VerifyWrite(originalPropertyDepth, writer); } return(true); } Type type = value.GetType(); if (type == typeof(object)) { writer.WriteStartObject(); writer.WriteEndObject(); return(true); } if (type != TypeToConvert) { // Handle polymorphic case and get the new converter. JsonConverter jsonConverter = state.Current.InitializeReEntry(type, options); if (jsonConverter != this) { // We found a different converter; forward to that. return(jsonConverter.TryWriteAsObject(writer, value, options, ref state)); } } } else if (value == null && !HandleNull) { // We do not pass null values to converters unless HandleNull is true. Null values for properties were // already handled in GetMemberAndWriteJson() so we don't need to check for IgnoreNullValues here. writer.WriteNullValue(); return(true); } if (ClassType == ClassType.Value) { Debug.Assert(!state.IsContinuation); int originalPropertyDepth = writer.CurrentDepth; Write(writer, value, options); VerifyWrite(originalPropertyDepth, writer); return(true); } bool isContinuation = state.IsContinuation; state.Push(); if (!isContinuation) { Debug.Assert(state.Current.OriginalDepth == 0); state.Current.OriginalDepth = writer.CurrentDepth; } bool success = OnTryWrite(writer, value, options, ref state); if (success) { VerifyWrite(state.Current.OriginalDepth, writer); // No need to clear state.Current.OriginalDepth since a stack pop will occur. } state.Pop(success); return(success); }
private static bool HandleDictionary( JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (state.Current.Enumerator == null) { IEnumerable enumerable; enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { // Write a null object or enumerable. state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, writeNull: true); return(true); } state.Current.Enumerator = enumerable.GetEnumerator(); state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer); } if (state.Current.Enumerator.MoveNext()) { // Handle DataExtension. if (ReferenceEquals(jsonPropertyInfo, state.Current.JsonClassInfo.DataExtensionProperty)) { WriteExtensionData(writer, ref state.Current); } else { // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { object currentValue = ((IDictionaryEnumerator)state.Current.Enumerator).Entry.Value; GetRuntimeClassInfo(currentValue, ref elementClassInfo, options); } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.GetPolicyProperty().WriteDictionary(ref state.Current, writer); } else if (state.Current.Enumerator.Current == null) { writer.WriteNull(jsonPropertyInfo.Name); } else { // An object or another enumerator requires a new stack frame. var enumerator = (IDictionaryEnumerator)state.Current.Enumerator; object value = enumerator.Value; state.Push(elementClassInfo, value); state.Current.KeyName = (string)enumerator.Key; } } return(false); } // We are done enumerating. writer.WriteEndObject(); if (state.Current.PopStackOnEnd) { state.Pop(); } else { state.Current.EndDictionary(); } return(true); }
private static bool HandleEnumerable( JsonClassInfo elementClassInfo, JsonSerializerOptions options, ref Utf8JsonWriter writer, ref WriteStack state) { Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable); JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (state.Current.Enumerator == null) { if (jsonPropertyInfo._name == null) { writer.WriteStartArray(); } else { writer.WriteStartArray(jsonPropertyInfo._name); } IEnumerable enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue, options); if (enumerable != null) { state.Current.Enumerator = enumerable.GetEnumerator(); } } if (state.Current.Enumerator != null && state.Current.Enumerator.MoveNext()) { // If the enumerator contains typeof(object), get the run-time type if (elementClassInfo.ClassType == ClassType.Object && jsonPropertyInfo.ElementClassInfo.Type == typeof(object)) { object currentValue = state.Current.Enumerator.Current; if (currentValue != null) { Type runtimeType = currentValue.GetType(); // Ignore object() instances since they are handled as an empty object. if (runtimeType != typeof(object)) { elementClassInfo = options.GetOrAddClass(runtimeType); } } } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.GetPolicyProperty().WriteEnumerable(options, ref state.Current, ref writer); } else if (state.Current.Enumerator.Current == null) { // Write a null object or enumerable. writer.WriteNullValue(); } else { // An object or another enumerator requires a new stack frame. object nextValue = state.Current.Enumerator.Current; state.Push(elementClassInfo, nextValue); } return(false); } // We are done enumerating. writer.WriteEndArray(); if (state.Current.PopStackOnEndArray) { state.Pop(); } else { state.Current.EndArray(); } return(true); }
private static bool HandleDictionary( JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (!jsonPropertyInfo.ShouldSerialize) { // Ignore writing this property. return(true); } if (state.Current.Enumerator == null) { // Verify that the Dictionary can be serialized by having <string> as first generic argument. Type[] args = jsonPropertyInfo.RuntimePropertyType.GetGenericArguments(); if (args.Length == 0 || args[0].UnderlyingSystemType != typeof(string)) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonClassInfo.Type, state.PropertyPath); } IEnumerable enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { // Write a null object or enumerable. state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, writeNull: true); return(true); } state.Current.Enumerator = enumerable.GetEnumerator(); state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer); } if (state.Current.Enumerator.MoveNext()) { // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { object currentValue = ((IDictionaryEnumerator)state.Current.Enumerator).Entry.Value; GetRuntimeClassInfo(currentValue, ref elementClassInfo, options); } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.GetPolicyProperty().WriteDictionary(options, ref state.Current, writer); } else if (state.Current.Enumerator.Current == null) { writer.WriteNull(jsonPropertyInfo.Name); } else { // An object or another enumerator requires a new stack frame. var enumerator = (IDictionaryEnumerator)state.Current.Enumerator; object value = enumerator.Value; state.Push(elementClassInfo, value); state.Current.KeyName = (string)enumerator.Key; } return(false); } // We are done enumerating. writer.WriteEndObject(); if (state.Current.PopStackOnEnd) { state.Pop(); } else { state.Current.EndDictionary(); } return(true); }