private object DeserializeArrayItem(string json, ref int currentReadIndex, int arrayItemIndex, SerializationContext context) { if (json[currentReadIndex] == 'n' && json[currentReadIndex + 1] == 'u' && json[currentReadIndex + 2] == 'l' && json[currentReadIndex + 3] == 'l') { currentReadIndex = currentReadIndex + 4; return(null); } //Type objectTargetType = null; if (json[currentReadIndex + 2] == '#' && json[currentReadIndex + 3] == 't' && json[currentReadIndex + 4] == 'y' && json[currentReadIndex + 5] == 'p' && json[currentReadIndex + 6] == 'e' ) { return(DeserializeSpecialType(json, ref currentReadIndex, context, currentReadIndex)); } object itemValue; if (this.isObject) { // determine target type during deserialization Type type = null; if (unknownTypeResolver != null) { context.Key = this.key; context.ValueStartIndex = currentReadIndex; context.ArrayIndex = arrayItemIndex; context.JsonString = json; type = unknownTypeResolver(context); context.ArrayIndex = null; } if (type == null || type.Equals(typeof(object))) { type = Structure.GetDefaultType(json, currentReadIndex); if (type == null) { int readCount = Math.Min(json.Length - currentReadIndex, 25); string jsonPart = json.Substring(currentReadIndex, readCount); throw new InvalidOperationException(string.Format("Unable to get the target type for array object index {0}; Key: {1}; JSON part: \"{2}\"", arrayItemIndex, this.key, jsonPart)); } } IJsonTypeStructure currentObjectStructure; if (!typeSerializerCache.TryGetValue(type, out currentObjectStructure)) { currentObjectStructure = Structure.DetermineStructure(type, GetNestedArrayKey(this.key, arrayItemIndex), context, true); typeSerializerCache[type] = currentObjectStructure; } itemValue = currentObjectStructure.Deserialize(json, ref currentReadIndex, context); } else { if (itemDeSerializer == null) { itemDeSerializer = Structure.DetermineStructure(itemType, key, context, true); } // fixed array target type itemValue = itemDeSerializer.Deserialize(json, ref currentReadIndex, context); } return(itemValue); }
// ---------------------------------------------------------------------------------------- #endregion #region StructureArray properties // ---------------------------------------------------------------------------------------- // StructureArray properties // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- #endregion #region StructureArray methods // ---------------------------------------------------------------------------------------- // StructureArray methods // ---------------------------------------------------------------------------------------- /// <summary> /// Serializes the specified object. /// </summary> /// <param name="sb">The string builder.</param> /// <param name="obj">The object to serialize.</param> /// <param name="context">The context.</param> public override void Serialize(StringBuilder sb, object obj, SerializationContext context) { if (keyExpected) { sb.Append(Structure.QuotationMark); sb.Append(key); if (obj == null) { sb.Append(Structure.QuotationColonNullValue); return; } else { sb.Append(Structure.QuotationColonSeparator); } } if (isByteArray) { // Optimization: add byte array as base64 encoded string sb.Append(Structure.CharQuotationMark); byte[] data = (byte[])obj; sb.Append(Convert.ToBase64String(data)); sb.Append(Structure.CharQuotationMark); } else { sb.Append(Structure.CharLeftSquareBrace); //Type collType = obj.GetType(); // check if own collection implementation exposes special target type // todo: check if possible and required //bool specialTypeAdded = false; //if (!collType.IsArray // && !IsSystemCollection(collType)) // //&& !checkedSubInterfaceTypes.Contains(collType)) //{ // var exposureAttributes = collType.GetCustomAttributes(typeof(ExposeSubTypeAttribute), false); // if (exposureAttributes.Length > 0) // { // // expose specialized sub interface type // if (this.typeSerializerCache == null) // this.typeSerializerCache = new Dictionary<Type, IJsonTypeStructure>(); // // add typed collection attribute // sb.Append(Structure.TypeMetaTagJson); // sb.Append(this.type.FullName); // sb.Append(Structure.CharQuotationMark); // specialTypeAdded = true; // } // //checkedSubInterfaceTypes.Add(collType); //} IEnumerable collection = (IEnumerable)obj; int count = 0; foreach (var item in collection) { //if (specialTypeAdded // && count == 0) //{ // sb.Append(Structure.CharComma); //} if (item != null) { if (isObject) { // determine serialize type Type itemType = item.GetType(); IJsonTypeStructure currentObjectStructure; if (!typeSerializerCache.TryGetValue(itemType, out currentObjectStructure)) { Type targetType = null; if (unknownTypeResolver != null) { context.Key = this.key; context.ArrayIndex = count; targetType = unknownTypeResolver(context); context.ArrayIndex = null; } if (targetType == null) { targetType = itemType; } currentObjectStructure = Structure.DetermineStructure(targetType, GetNestedArrayKey(this.key, count), context, true); typeSerializerCache[itemType] = currentObjectStructure; } currentObjectStructure.Serialize(sb, item, context); } else { if (itemSerializer == null) { this.itemSerializer = Structure.DetermineStructure(itemType, key, context, true); } // use static serialize type itemSerializer.Serialize(sb, item, context); } } else { sb.Append(Structure.NullValue); } sb.Append(Structure.CharComma); count++; } if (count > 0) { sb.Length -= 1; // remove last comma } sb.Append(Structure.CharRightSquareBracet); } }