public void Read(IObjectReconstructor reconstructor, ISerializer serializer) { var count = _container.GetCount(); for (var i = 0; i < count; i++) { var valueInfo = new ValueInfo { Name = _container.GetName(i), Type = _container.GetType(i).ToTypeSerializationInfo(), }; reconstructor.OnValueStart(valueInfo); reconstructor.OnValue(_container.GetValue(i)); reconstructor.OnValueEnd(); } }
public void Read(IObjectReconstructor reconstructor, ISerializer serializer) { var stateStack = new Stack <State>(); State state = null; while (_jsonReader.Read()) { switch (_jsonReader.TokenType) { case JsonToken.StartObject: { if (state?.Info.Name != null && reconstructor.GetExpectedValueType(state.Info.Name) == typeof(IValueContainer)) { var content = new StringBuilder(); var textWriter = new StringWriter(content); var jsonWriter = new JsonTextWriter(textWriter); jsonWriter.WriteToken(_jsonReader, writeChildren: true); var serializedContainer = new SerializedValueContainer( content.ToString(), serializer); reconstructor.OnValueStart(state.Info); reconstructor.OnValue(serializedContainer); reconstructor.OnValueEnd(); if (stateStack.Count > 0) { state = stateStack.Pop(); if (state.Info.IsCollection) { stateStack.Push(state); state = new State(); } } else { state = null; } } else { if (state == null) { state = new State(); } state.HasMetadata = true; } } break; case JsonToken.EndObject: { if (state.ValueStarted && !state.ValueEnded) { reconstructor.OnValueEnd(); state.ValueEnded = true; } else if (!state.ValueStarted && (state.Info.ReferenceId != null || state.Info.SpecialId != null)) { reconstructor.OnValueStart(state.Info); reconstructor.OnValueEnd(); } if (stateStack.Count > 0) { state = stateStack.Pop(); if (state.Info.IsCollection) { stateStack.Push(state); state = new State(); } } else { state = null; } } break; case JsonToken.PropertyName: { var name = (string)_jsonReader.Value; if (name[0] == '$') { if (name == "$id") { ReadObjectId(ref state.Info); } else if (name == "$itemCount") { ReadItemCount(ref state.Info); } else if (name == "$type") { state.Info.Type = ReadTypeInfo(); } else if (name == "$itemType") { state.Info.IsCollection = true; state.Info.ItemType = ReadTypeInfo(); } else if (name == "$items") { state.Info.IsCollection = true; if (!state.ValueStarted) { reconstructor.OnValueStart(state.Info); state.ValueStarted = true; } } else if (name == "$value") { if (!state.ValueStarted) { reconstructor.OnValueStart(state.Info); state.ValueStarted = true; } } else if (name == "$typeIsValue") { if (ReadTypeIsValue()) { var value = state.Info.Type; if (!state.ValueStarted) { state.Info.Type = TypeSerializationInfo.Self; reconstructor.OnValueStart(state.Info); state.ValueStarted = true; } reconstructor.OnValue(value); } } else { throw new InvalidOperationException($"Unknown directive '{name}'"); } } else { if (!state.ValueStarted) { reconstructor.OnValueStart(state.Info); state.ValueStarted = true; } stateStack.Push(state); state = new State { Info = new ValueInfo { Name = name } }; } } break; case JsonToken.StartArray: { state.Info.IsCollection = true; if (!state.ValueStarted) { reconstructor.OnValueStart(state.Info); state.ValueStarted = true; } stateStack.Push(state); state = new State(); } break; case JsonToken.EndArray: { state = stateStack.Pop(); if (!state.HasMetadata && state.ValueStarted) { reconstructor.OnValueEnd(); state.ValueEnded = true; } } break; case JsonToken.Boolean: case JsonToken.Bytes: case JsonToken.Date: case JsonToken.Float: case JsonToken.Integer: case JsonToken.Null: case JsonToken.String: { if (!state.HasMetadata) { reconstructor.OnValueStart(state.Info); } reconstructor.OnValue(_jsonReader.Value); if (!state.HasMetadata) { reconstructor.OnValueEnd(); if (state.Info.Name != null) { state = stateStack.Pop(); } } } break; default: throw new InvalidOperationException( $"Unexpected JSON token '{_jsonReader.TokenType}'."); } } }