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> /// Parses a javascript object /// </summary> /// <returns></returns> private ObjectExpression ParseObject() { Token tok = ReadToken(); Debug.Assert(tok == LBraceToken); ObjectExpression value = new ObjectExpression(); Expression item; while (ReadAhead(CommaToken, RBraceToken, new ExpressionMethod(ParseKeyValue), out item)) { value.Add((KeyValueExpression)item); } return value; }
public void Visit(ObjectExpression objExpr) { VisitComplex(objExpr); foreach (KeyValueExpression item in objExpr.Properties) Visit(item); }
/// <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 ComplexExpressionBase 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>(); while (ReadAhead(CommaToken, RParenToken, new ExpressionMethod(ParseExpression), out arg)) { ConstructorArgs.Add(arg); } ComplexExpressionBase value = null; if (PeekToken() == LSquareToken || PeekToken() == LBraceToken) { value = (ComplexExpressionBase) ParseExpression(); } else { value = new ObjectExpression(); } value.ResultType = t; value.ConstructorArguments = ConstructorArgs; return value; }
/// <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> /// 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> /// 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> /// 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; }