public void RootObjectTest() { ObjectExpression rootAsObject = new ObjectExpression(); Expression result = ResolveReference(rootAsObject, JsonPath.Root); Assert.AreSame(rootAsObject, result, "Resolve reference for this should return root"); }
/// <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, IExpressionBuilder 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; }
protected virtual Expression GetColumnExpression(DataColumn dc, JsonPath jsonPath, IExpressionBuilder serializer) { ObjectExpression column = new ObjectExpression(); // just DataType and column for now column.Add("DataType", serializer.Serialize(dc.DataType, jsonPath.Append("DataType"))); column.Add("ColumnName", serializer.Serialize(dc.ColumnName, jsonPath.Append("ColumnName"))); return column; }
public override Expression GetExpression(object data, JsonPath currentPath, IExpressionBuilder serializer) { DataTable table = (DataTable) data; ObjectExpression tableExpr = new ObjectExpression(); tableExpr.Add("TableName", serializer.Serialize(table.TableName, currentPath.Append("TableName"))); tableExpr.Add("Columns", GetColumnsExpression(table, currentPath.Append("Columns"), serializer)); tableExpr.Add("Rows", GetRowsExpression(table, currentPath, serializer)); return tableExpr; }
public virtual void Visit(ObjectExpression expression) { OnObjectStart(expression); Visit((ComplexExpressionBase)expression); foreach (KeyValueExpression kv in expression.Properties) { kv.Accept(this); } OnObjectEnd(expression); }
public void ResolveObjectObjectTest() { ObjectExpression root = new ObjectExpression(); ObjectExpression child1 = new ObjectExpression(); root.Add(new ValueExpression("child1"), child1); ObjectExpression child2 = new ObjectExpression(); root.Add(new ValueExpression("child2"), child2); Expression actual = ResolveReference(root, "$['child2']"); Assert.AreSame(child2, actual, "this.child2 did not resolve correctly"); }
public void ResolveCollectionItemTest() { ArrayExpression root = new ArrayExpression(); ObjectExpression child1 = new ObjectExpression(); ObjectExpression child2 = new ObjectExpression(); root.Add(child1); root.Add(child2); Expression actual = ResolveReference(root, "$[1]"); Assert.AreSame(child2, actual, "$[1] did not resolve correctly"); }
/// <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, IExpressionBuilder serializer) { TypeData handler = Config.GetTypeHandler(data.GetType()); ObjectExpression expression = new ObjectExpression(); foreach (IPropertyData prop in handler.Properties) { GenerateItemExpression(data, currentPath, serializer, expression, prop); } return expression; }
public void Deserialize_When2CtorsWithSameArgCount_EvaluateCorrectOne() { Serializer s = new Serializer(typeof(CtorMock)); ObjectExpression expr = new ObjectExpression(); expr.ResultType = typeof(CtorMock); NumericExpression IDExpr = new NumericExpression("10"); ValueExpression StrExpr = new ValueExpression("name"); expr.ConstructorArguments.Add(IDExpr); expr.ConstructorArguments.Add(StrExpr); CtorArgTypeResolver resolver = new CtorArgTypeResolver(expr,s.Config); Type[] argTypes = resolver.ResolveTypes(); CollectionAssert.AreElementsEqual(new Type[] { typeof(int), typeof(string) }, argTypes); }
public void ResolveNestedObjectTest() { ObjectExpression root = new ObjectExpression(); ObjectExpression child1 = new ObjectExpression(); root.Add(new ValueExpression("child1"), child1); ObjectExpression child2 = new ObjectExpression(); root.Add(new ValueExpression("child2"), child2); ObjectExpression childA = new ObjectExpression(); child1.Add(new ValueExpression("childA"), childA); ObjectExpression childB = new ObjectExpression(); child2.Add(new ValueExpression("childB"), childB); Expression actual = ResolveReference(root, "$['child2']['childB']"); Assert.AreSame(childB, actual, "$['child2']['childB'] did not resolve correctly"); }
public void VisitObject(ObjectExpression expression) { Visit(typeof(ComplexExpressionBase), expression); if (_expr != null) return; // found it string key = _refID.Top; foreach (KeyValueExpression exp in expression.Properties) { if (exp.Key == key) { Visit(exp); return; } } // if we get here we didn't find it throw new Exception("Unable to resolve reference: " + _refID); }
/// <summary> /// Generates an expression for an item and adds it to the object /// </summary> /// <param name="data">the item being serialized</param> /// <param name="currentPath">the current path to the object</param> /// <param name="serializer">serializer instance</param> /// <param name="expression">the object expression</param> /// <param name="prop">the property being serialized</param> protected virtual void GenerateItemExpression(object data, JsonPath currentPath, IExpressionBuilder serializer, ObjectExpression expression, IPropertyData prop) { object value = prop.GetValue(data); if (!prop.ShouldWriteValue(this.Config, value)) return; Expression valueExpr; if (prop.HasConverter) { valueExpr = serializer.Serialize(value, currentPath.Append(prop.Alias), prop.TypeConverter); } else { valueExpr = serializer.Serialize(value, currentPath.Append(prop.Alias)); } if (value != null && !ReflectionUtils.AreEquivalentTypes(value.GetType(), prop.PropertyType)) { valueExpr = new CastExpression(value.GetType(), valueExpr); } expression.Add(prop.Alias, valueExpr); }
public void Deserialize_UseCorrectTypes_WhenParametersDefined() { Serializer s = new Serializer(typeof(CtorMock2)); ObjectExpression expr = new ObjectExpression(); expr.ResultType = typeof(CtorMock2); NumericExpression IDExpr = new NumericExpression("10"); ObjectExpression objExpr = new ObjectExpression(); objExpr.ConstructorArguments.Add(new ValueExpression("name")); expr.ConstructorArguments.Add(IDExpr); expr.ConstructorArguments.Add(objExpr); Type[] definedTypes = new Type[] { typeof(int), typeof(MyObject2) }; CtorArgTypeResolver resolver = new CtorArgTypeResolver(expr, s.Config, definedTypes); Type[] argTypes = resolver.ResolveTypes(); CollectionAssert.AreElementsEqual(new Type[] { typeof(long), typeof(MyObject2) }, argTypes); // Try to construct IDExpr.ResultType = typeof(long); objExpr.ResultType = typeof(MyObject2); Evaluator eval = new Evaluator(s.Config); object result = eval.Evaluate(expr); }
/// <summary> /// Called on an object expression before the properties and constructor arguments are visited /// </summary> /// <param name="expression"></param> public virtual void OnObjectStart(ObjectExpression expression) { }
/// <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; }
/// <summary> /// Resolves and updates the types of any constructor arguments /// </summary> /// <param name="context">serialization context</param> /// <param name="expression">object expression</param> protected static void ResolveConstructorTypes(SerializationContext context, ObjectExpression expression) { TypeData handler = context.GetTypeHandler(expression.ResultType); Type[] definedTypes = GetConstructorParameterTypes(handler.ConstructorParameters); CtorArgTypeResolver resolver = new CtorArgTypeResolver(expression, context, definedTypes); Type[] resolvedTypes = resolver.ResolveTypes(); for (int i = 0; i < resolvedTypes.Length; i++) { if (resolvedTypes[i] != null) expression.ConstructorArguments[i].ResultType = resolvedTypes[i]; } }
/// <summary> /// Constructs a new instance of the object represented by the expression. /// </summary> /// <param name="expression">json object expression</param> /// <param name="deserializer">deserializer for deserializing constructor arguments if any</param> /// <returns>constructed, but unpopulated object</returns> protected virtual object ConstructObject(ObjectExpression expression, IDeserializerHandler deserializer) { TypeData handler = Context.GetTypeHandler(expression.ResultType); // set the default type if none set if (expression.ConstructorArguments.Count > 0) { // old way expects parameters in the constructor list ResolveConstructorTypes(Context, expression); } else { foreach (IPropertyData parameter in handler.ConstructorParameters) { int propLocation = expression.IndexOf(parameter.Name); if (propLocation >= 0) { Expression arg = expression.Properties[propLocation].ValueExpression; arg.ResultType = parameter.PropertyType; expression.ConstructorArguments.Add(arg); expression.Properties.RemoveAt(propLocation); } else { expression.ConstructorArguments.Add(new NullExpression()); } } } object[] args = new object[expression.ConstructorArguments.Count]; for (int i = 0; i < args.Length; i++) { Expression carg = expression.ConstructorArguments[i]; args[i] = deserializer.Evaluate(carg); } object result = handler.CreateInstance(args); expression.OnObjectConstructed(result); return result; }
/// <summary> /// Parses a constructor expression /// </summary> /// <returns>complex expression</returns> /// <example> /// new MyType("arg1", "arg2") /// new MyType("argA", "argB") { "argC": "C", "argD": "D" } /// </example> private Expression ParseConstructedObject() { Token tok = ReadToken(); // should be the new keyword Debug.Assert(tok == NewToken); Type t = ParseTypeSpecifier(); tok = ReadToken(); RequireToken(LParenToken, tok, "Missing constructor arguments"); Expression arg; List<Expression> ConstructorArgs = new List<Expression>(); bool first = true; while (ReadAhead(CommaToken, RParenToken, new ExpressionMethod(ParseExpression), out arg, ref first)) { ConstructorArgs.Add(arg); } ComplexExpressionBase value = null; if (PeekToken() == LSquareToken || PeekToken() == LBraceToken) { value = (ComplexExpressionBase) ParseExpression(); } else { value = new ObjectExpression(); } value.ResultType = t; value.ConstructorArguments = ConstructorArgs; // insert Cast to keep type from being overwritten return new CastExpression(t,value); }
public void ResolveNestedCollectionTest() { ArrayExpression root = new ArrayExpression(); ArrayExpression child1 = new ArrayExpression(); ArrayExpression child2 = new ArrayExpression(); root.Add(child1); root.Add(child2); ObjectExpression childA = new ObjectExpression(); child1.Add(childA); ObjectExpression childB = new ObjectExpression(); child1.Add(childB); Expression actual = ResolveReference(root, "$[0][1]"); Assert.AreSame(childB, actual, "$[0][1] did not resolve correctly"); }
/// <summary> /// Called on an object expression after the properties and constructor arguments are visited /// </summary> /// <param name="expression"></param> public virtual void OnObjectEnd(ObjectExpression expression) { }
/// <summary> /// Parses a javascript object /// </summary> /// <returns></returns> private ObjectExpression ParseObject() { Token tok = ReadToken(); Debug.Assert(tok == LBraceToken); ObjectExpression value = new ObjectExpression(); Expression item; bool first = true; while (ReadAhead(CommaToken, RBraceToken, new ExpressionMethod(ParseKeyValue), out item, ref first)) { value.Add((KeyValueExpression)item); } return value; }
public override void OnObjectStart(ObjectExpression expression) { // inspect the "type" property if available and set the correct type on the "value" if (expression["type"] != null && expression["value"] != null) { string typeIndc = ((ValueExpression)expression["type"]).StringValue; Type newType = null; if (typeIndc == "Type1") newType = typeof(Type1); else if (typeIndc == "Type2") newType = typeof(Type2); if (newType != null) expression["value"] = new CastExpression(newType, expression["value"]); } }
public void Visit(ObjectExpression objExpr) { VisitComplex(objExpr); foreach (KeyValueExpression item in objExpr.Properties) Visit(item); }