protected virtual Expression GetExpression(IEnumerable Items, Type ItemType, JsonPath CurrentPath, ISerializerHandler serializer) { int index = 0; ArrayExpression expression = new ArrayExpression(); foreach (object value in Items) { Expression itemExpr = serializer.Serialize(value, CurrentPath.Append(index)); if (value != null && !ReflectionUtils.AreEquivalentTypes(value.GetType(), ItemType)) { itemExpr = new CastExpression(value.GetType(), itemExpr); } expression.Add(itemExpr); index++; } return expression; }
public Expression HandleReference(object value, JsonPath CurrentPath) { if (!IsReferenceable(value)) return null; ReferenceInfo refInfo = null; if (_refs.ContainsKey(value)) { /* * This object has already been seen by the serializer so * determine what to do with it. If its part of the current path * then its a circular reference and an error needs to be thrown or it should * be ignored depending on the option. Otherwise write a reference to it */ refInfo = _refs[value]; JsonPath refPath = refInfo.Path; switch (_context.ReferenceWritingType) { case SerializationContext.ReferenceOption.WriteIdentifier: if (!refInfo.CanReference) throw new InvalidOperationException("Can't reference object: " + refPath + " from " + CurrentPath + ", either it is a collection, or it has not been converted yet"); return new ReferenceExpression(refPath); case SerializationContext.ReferenceOption.IgnoreCircularReferences: if (CurrentPath.StartsWith(refPath)) { return new NullExpression(); } break; case SerializationContext.ReferenceOption.ErrorCircularReferences: if (CurrentPath.StartsWith(refPath)) { throw new InvalidOperationException("Circular reference detected. Current path: " + CurrentPath + ", reference to: " + refPath); } break; } } else { refInfo = new ReferenceInfo(CurrentPath); _refs[value] = refInfo; } return null; }
public void VisitComplexBase(ComplexExpressionBase expression) { if (_refID.Top == JsonPath.Root) { if (expression.Parent != null) { throw new ArgumentException("Reference for this passed to object that is not at the root", "refID"); } } else { // have to assume that the parent checked that we were the right reference // should only get here if we have a parent, if no parent we're not valid if (expression.Parent == null) throw new ArgumentException("Invalid reference", "refID"); } // it is this object, check if we need to go further _refID = _refID.ChildReference(); if (_refID.IsEmpty) { _expr = expression; } }
/// <summary> /// Gets an expression for a value by first converting it with its registered type converter and then calling Serialize /// </summary> /// <param name="value">the value to generate an expression for</param> /// <param name="currentPath">the current path to the value</param> /// <param name="serializer">serializer instance</param> /// <returns>an expression for the value</returns> public override Expression GetExpression(object value, JsonPath currentPath, ISerializerHandler serializer) { TypeData handler = Context.TypeHandlerFactory[value.GetType()]; IJsonTypeConverter converter = (handler.HasConverter ? handler.TypeConverter : (IJsonTypeConverter)value); return GetExpression(value, converter, currentPath, serializer); }
/// <summary> /// Serializes the data into a json array expression. /// </summary> /// <param name="data">the data to serialize</param> /// <param name="currentPath">the current path to the data</param> /// <param name="serializer">serializer instance to use to serialize list items</param> /// <returns>a json array expression representation</returns> public override Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer) { TypeData handler = Context.GetTypeHandler(data.GetType()); CollectionHandler collectionHandler = handler.GetCollectionHandler(); Type elemType = collectionHandler.GetItemType(handler.ForType); int index = 0; ArrayExpression expression = new ArrayExpression(); foreach (object value in collectionHandler.GetEnumerable(data)) { Expression itemExpr = serializer.Serialize(value, currentPath.Append(index)); if (value != null && !ReflectionUtils.AreEquivalentTypes(value.GetType(), elemType)) { itemExpr = new CastExpression(value.GetType(), itemExpr); } expression.Add(itemExpr); index++; } return expression; }
public bool StartsWith(JsonPath value) { return(this.ToString().StartsWith(value.ToString())); }
/// <summary> /// Parses a reference to an object /// </summary> /// <returns></returns> private Expression ParseReference() { JsonPath refID = new JsonPath(); Token tok = ReadToken(); if (tok != ReferenceStartToken && tok != OldReferenceStartToken) throw new ParseException(string.Format("Invalid starting token for ParseReference, Expected: {0} or {1}, got: {2}", ReferenceStartToken, OldReferenceStartToken,tok)); while (PeekToken() == PeriodToken || PeekToken() == LSquareToken) { tok = ReadToken(); // separator "." if (tok == PeriodToken) tok = ReadToken(); // type part if (tok == LSquareToken) { refID = refID.Append(ReadToken().value); // index ReadToken(); // ] } else if (tok.type == TokenType.Identifier) { refID = refID.Append(tok.value); } else { throw new ParseException("Invalid Reference, must be an identifier or array value: " + tok); } } return new ReferenceExpression(refID); }
public override Expression GetExpression(object data, JsonPath CurrentPath, ISerializerHandler serializer) { return GetExpression((IEnumerable)data, GetItemType(data.GetType()), CurrentPath, serializer); }
public ReferenceVisitor(JsonPath RefID) { _refID = RefID; }
public bool StartsWith(JsonPath value) { return this.ToString().StartsWith(value.ToString()); }
/// <summary> /// Serialize the given object at the current indent level. The path to the object is represented by /// currentPath such as "this.name", etc. This is an internal method that can be called recursively. /// </summary> /// <param name="value">the object to serialize</param> /// <param name="currentPath">the current path for reference writing</param> public Expression Serialize(object value, JsonPath currentPath, IJsonTypeConverter converter) { if (value == null) { return new NullExpression(); } else { Expression expr = HandleReference(value, currentPath); if (expr != null) return expr; ISerializationCallback callback = value as ISerializationCallback; if (callback != null) callback.OnBeforeSerialization(); try { //TODO: this is too early for converters SetCanReference(value); // regular object, can reference at any time IExpressionHandler objHandler; if (converter != null) { TypeConverterExpressionHandler converterHandler = (TypeConverterExpressionHandler)_context.ExpressionHandlers.Find(typeof(TypeConverterExpressionHandler)); //TODO: make sure it exists return converterHandler.GetExpression(value, converter, currentPath, this); } objHandler = _context.ExpressionHandlers.GetHandler(value); return objHandler.GetExpression(value, currentPath, this); } finally { if (callback != null) callback.OnAfterSerialization(); } } }
public override Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer) { string value = ((DateTime)data).ToString(dateFormat, Culture); return new ValueExpression(value); }
/// <summary> /// Serialize an object implementing IDictionary. The serialized data is similar to a regular /// object, except that the keys of the dictionary are used instead of properties. /// </summary> /// <param name="data">the dictionary object</param> /// <param name="currentPath">object's path</param> /// <param name="serializer">the serializer instance, used to serialize keys and values</param> public override Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer) { IDictionary dictionary = (IDictionary)data; Type itemType = typeof(object); Type genericDictionary = null; if ((genericDictionary = dictionary.GetType().GetInterface(typeof(IDictionary<,>).Name)) != null) { itemType = genericDictionary.GetGenericArguments()[1]; } ObjectExpression expression = new ObjectExpression(); foreach (DictionaryEntry pair in dictionary) { //may not work in all cases object value = pair.Value; Expression valueExpr = serializer.Serialize(value, currentPath.Append(pair.Key.ToString())); if (value != null && !ReflectionUtils.AreEquivalentTypes(value.GetType(), itemType)) { valueExpr = new CastExpression(value.GetType(), valueExpr); } expression.Add(pair.Key.ToString(), valueExpr); } return expression; }
public Expression Serialize(object value, JsonPath currentPath) { return Serialize(value, currentPath, null); }
public ReferenceExpression(JsonPath ReferencePath) { this._path = ReferencePath; }
public ReferenceExpression(string ReferencePath) { this._path = new JsonPath(ReferencePath); }
/// <summary> /// Returns a reference expression to the current data /// </summary> /// <param name="data">the object data</param> /// <param name="currentPath">current path to this object</param> /// <param name="serializer">serializer instance</param> /// <returns>reference expression</returns> public override Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer) { return serializer.HandleReference(data, currentPath); }
/// <summary> /// Gets an expression for a value by first converting it with a specific type converter and then calling Serialize. This /// method can be called directly when using a Property Converter /// </summary> /// <param name="value">the value to generate an expression for</param> /// <param name="converter">the type converter to use for conversion</param> /// <param name="currentPath">the current path to the value</param> /// <param name="serializer">serializer instance</param> /// <returns>an expression for the value</returns> public Expression GetExpression(object value, IJsonTypeConverter converter, JsonPath currentPath, ISerializerHandler serializer) { object convertedObject = converter.ConvertFrom(value, Context); // call serialize again in case the new type has a converter Expression expr = serializer.Serialize(convertedObject, currentPath, null); serializer.SetCanReference(value); // can't reference inside the object return expr; }
/// <summary> /// Creates a null expression /// </summary> /// <param name="data">the data</param> /// <param name="currentPath">current path</param> /// <param name="serializer">serializer instance</param> /// <returns>NullExpression</returns> public override Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer) { return new NullExpression(); }
/// <summary> /// Creates an json object expression from object data. /// </summary> /// <param name="data">the data to serialize</param> /// <param name="currentPath">current path to the object</param> /// <param name="serializer">serializer instance used to serialize key values</param> /// <returns>json object expression</returns> public override Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer) { TypeData handler = Context.GetTypeHandler(data.GetType()); ObjectExpression expression = new ObjectExpression(); foreach (IPropertyData prop in handler.Properties) { object value = prop.GetValue(data); Expression valueExpr; if (prop.HasConverter) { valueExpr = serializer.Serialize(value, currentPath.Append(prop.Name), prop.TypeConverter); } else { valueExpr = serializer.Serialize(value, currentPath.Append(prop.Name)); } if (value != null && !ReflectionUtils.AreEquivalentTypes(value.GetType(), prop.PropertyType)) { valueExpr = new CastExpression(value.GetType(), valueExpr); } expression.Add(prop.Name, valueExpr); } return expression; }
public ReferenceInfo(JsonPath Path) { this.Path = Path; }
/// <summary> /// GetExpression is not valid for a CastExpression. CastExpressions should be created directly /// during serialization whenever type information is needed. /// </summary> /// <param name="data">data to serialize</param> /// <param name="currentPath">the current path to the object</param> /// <param name="serializer">serializer instance</param> /// <returns>expression</returns> /// <exception cref="InvalidOperationException">This will throw an exception if called</exception> public override Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer) { throw new InvalidOperationException("CastObjectHandler should not be called during Serialization"); }
/// <summary> /// Take an object and convert it to an expression to be serialized. Child names/indexes should be appended to the /// currentPath before serializing child objects. /// </summary> /// <param name="data">the object to convert</param> /// <param name="CurrentPath">the current path to this object from the root, used for tracking references</param> /// <param name="serializer">serializer instance for serializing child objects</param> /// <returns>an expression which represents a json structure</returns> public abstract Expression GetExpression(object data, JsonPath currentPath, ISerializerHandler serializer);
private Expression _reference; // the expression that is referenced #endregion Fields #region Constructors public ReferenceExpression(string ReferencePath) { this._path = new JsonPath(ReferencePath); }