// There are three conditions to consider for an object (primitive value, enumerable or object) being processed here: // 1) The object type was specified as the root-level return type to a Parse\Read method. // 2) The object is property on a parent object. // 3) The object is an element in an enumerable. private static bool Write( Utf8JsonWriter writer, int originalWriterDepth, int flushThreshold, JsonSerializerOptions options, ref WriteStack state) { bool finishedSerializing; try { do { WriteStackFrame current = state.Current; switch (current.JsonClassInfo.ClassType) { case ClassType.Enumerable: finishedSerializing = HandleEnumerable(current.JsonClassInfo.ElementClassInfo, options, writer, ref state); break; case ClassType.Value: Debug.Assert(current.JsonPropertyInfo.ClassType == ClassType.Value); current.JsonPropertyInfo.Write(ref state, writer); finishedSerializing = true; break; case ClassType.Object: finishedSerializing = WriteObject(options, writer, ref state); break; case ClassType.Dictionary: case ClassType.IDictionaryConstructible: finishedSerializing = HandleDictionary(current.JsonClassInfo.ElementClassInfo, options, writer, ref state); break; default: Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Unknown); // Treat typeof(object) as an empty object. finishedSerializing = WriteObject(options, writer, ref state); break; } if (finishedSerializing) { if (writer.CurrentDepth == 0 || writer.CurrentDepth == originalWriterDepth) { break; } } else if (writer.CurrentDepth >= options.EffectiveMaxDepth) { ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(options.MaxDepth); } // If serialization is not yet end and we surpass beyond flush threshold return false and flush stream. if (flushThreshold >= 0 && writer.BytesPending > flushThreshold) { return(false); } } while (true); } catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException) { ThrowHelper.ReThrowWithPath(state, ex); } catch (JsonException ex) { ThrowHelper.AddExceptionInformation(state, ex); throw; } return(true); }