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();
            }
        }
Exemple #2
0
        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}'.");
                }
            }
        }