public void SetProperty(IDeserializerNode targetNode, PropertySpec property, object propertyValue) { if (targetNode.Operation == DeserializerNodeOperation.Default) { throw new InvalidOperationException("Invalid deserializer node operation default"); } if ((targetNode.Operation == DeserializerNodeOperation.Post && property.AccessMode.HasFlag(HttpMethod.Post)) || (targetNode.Operation == DeserializerNodeOperation.Patch && property.AccessMode.HasFlag(HttpMethod.Put))) { property.SetValue(targetNode.Value, propertyValue, targetNode.Context); } else { var propPath = string.IsNullOrEmpty(targetNode.ExpandPath) ? property.Name : targetNode.ExpandPath + "." + property.Name; throw new ResourceValidationException( $"Property {property.Name} of resource {targetNode.ValueType.Name} is not writable.", propPath, targetNode.ValueType.Name, null); } }
public PropertyValueDeserializerNode(IDeserializerNode parent, PropertySpec property) { Parent = parent; Property = property; ValueType = property.PropertyType; Context = parent.Context; }
public PropertyValueDeserializerNode(IDeserializerNode parent, PropertySpec property) { this.parent = parent; this.property = property; this.valueType = property.PropertyType; this.context = parent.Context; }
public object CreateReference(IDeserializerNode node) { var uri = node.Uri; var type = node.ValueType; /* * if (type.Type.IsGenericType && type.Type.GetGenericTypeDefinition() == typeof(ClientRepository<,>)) * { * if (node.Parent != null) * { * var childRepositoryType = * typeof(ChildResourceRepository<,>).MakeGenericType(type.Type.GetGenericArguments()); * return Activator.CreateInstance(childRepositoryType, client, uri, null, node.Parent.Value); * } * return Activator.CreateInstance(type.Type, client, uri, null); * }*/ if (type.SerializationMode == TypeSerializationMode.Array) { return(LazyCollectionProxy.CreateForType(type, uri, this.client)); } if (type is StructuredType && type.SerializationMode == TypeSerializationMode.Structured) { var clientType = (StructuredType)type; var proxyType = clientType.ResourceInfo.LazyProxyType; var refobj = (LazyProxyBase)Activator.CreateInstance(proxyType); refobj.Initialize(uri, this.resourceLoader, clientType.ResourceInfo.PocoType, node.ExpandPath); return(refobj); } throw new NotImplementedException("Don't know how to make reference to type " + type.Name + " yet!"); }
private void DeserializeDictionary(IDeserializerNode node, Reader reader) { if (TryDeserializeAsReference(node, reader)) { return; } var dictType = node.ExpectedBaseType as DictionaryTypeSpec; if (dictType == null) { dictType = (DictionaryTypeSpec)node.Context.GetClassMapping(typeof(Dictionary <string, object>)); } var keyType = dictType.KeyType.Type; if (keyType != typeof(string)) { throw new NotImplementedException( "Only supports deserialization to IDictionary<TKey,TValue> where TKey is of type string."); } var valueType = dictType.ValueType.Type; deserializeDictionaryGenericMethod(valueType, this, node, reader, dictType); }
private void DeserializeComplexNode(IDeserializerNode node, Reader reader) { if (TryDeserializeAsReference(node, reader)) { return; } var jobj = reader.Token as JObject; if (jobj == null) { throw new PomonaSerializationException( "Trying to deserialize to complex type, expected a JSON object type but got " + reader.Token.Type); } SetNodeValueType(node, jobj); if (node.Operation == DeserializerNodeOperation.Default) { node.Operation = node.Value == null ? DeserializerNodeOperation.Post : DeserializerNodeOperation.Patch; } var propertyValueSource = new PropertyValueSource(jobj, node, this); propertyValueSource.Deserialize(); }
private static bool TryDeserializeAsReference(IDeserializerNode node, Reader reader) { var jobj = reader.Token as JObject; if (jobj == null) { return(false); } SetNodeValueType(node, jobj); JToken refStringToken; if (!jobj.TryGetValue("_ref", out refStringToken) || refStringToken.Type != JTokenType.String) { return(false); } var refString = (string)((JValue)refStringToken).Value; node.Uri = refString; try { node.Value = node.Context.CreateReference(node); } catch (Exception ex) { throw new PomonaSerializationException("Failed to deserialize: " + ex.Message, ex); } return(true); }
public void OnMissingRequiredPropertyError(IDeserializerNode node, PropertySpec targetProp) { throw new ResourceValidationException( $"Property {targetProp.Name} is required when creating resource {node.ValueType.Name}", targetProp.Name, node.ValueType.Name, null); }
public PropertyValueSource(JObject jobj, IDeserializerNode node, PomonaJsonDeserializer deserializer) { this.node = node; this.deserializer = deserializer; this.propertyDict = jobj.Properties() .Select(x => new PropertyContainer(x)) .ToDictionary(x => x.Name, x => x, StringComparer.InvariantCultureIgnoreCase); }
private void DeserializeDictionaryGeneric <TValue>(IDeserializerNode node, Reader reader, DictionaryTypeSpec dictType) { IDictionary <string, TValue> dict; if (node.Value != null) { dict = (IDictionary <string, TValue>)node.Value; } else { dict = new Dictionary <string, TValue>(); } var jobj = reader.Token as JObject; var valueType = dictType.ValueType; if (jobj == null) { throw new PomonaSerializationException( "Expected dictionary property to have a JSON object value, but was " + reader.Token.Type); } foreach (var jprop in jobj.Properties()) { var jpropName = jprop.Name; if (jpropName.Length > 0 && reservedFirstCharacters.Contains(jpropName[0])) { if (jpropName[0] == '-') { // Removal operation var unescapedPropertyName = UnescapePropertyName(jpropName.Substring(1)); dict.Remove(unescapedPropertyName); } else { throw new PomonaSerializationException( "Unexpected character in json property name. Have propertie names been correctly escaped?"); } } else { var unescapedPropertyName = UnescapePropertyName(jpropName); var itemNode = new ItemValueDeserializerNode(valueType, node.Context, node.ExpandPath + "." + unescapedPropertyName); DeserializeThroughContext(itemNode, new Reader(jprop.Value)); dict[unescapedPropertyName] = (TValue)itemNode.Value; } } if (node.Value == null) { node.Value = dict; } }
public ItemValueDeserializerNode(TypeSpec expectedBaseType, IDeserializationContext context, string expandPath = "", IDeserializerNode parent = null) { this.parent = parent; this.expectedBaseType = expectedBaseType; this.context = context; this.expandPath = expandPath; valueType = expectedBaseType; }
public ItemValueDeserializerNode(TypeSpec expectedBaseType, IDeserializationContext context, string expandPath = "", IDeserializerNode parent = null) { Parent = parent; ExpectedBaseType = expectedBaseType; Context = context; ExpandPath = expandPath; this.valueType = expectedBaseType; }
public void Deserialize(IDeserializerNode node, Action <IDeserializerNode> nodeDeserializeAction) { nodeDeserializeAction(node); var transformedType = node.ValueType as StructuredType; if (transformedType != null && transformedType.OnDeserialized != null && node.Value != null) { transformedType.OnDeserialized(node.Value); } }
public void Deserialize(IDeserializerNode node, Action <IDeserializerNode> deserializeNodeAction) { deserializeNodeAction(node); if (node.Uri != null) { var uriResource = node.Value as IHasSettableResourceUri; if (uriResource != null) { uriResource.Uri = node.Uri; } } }
public void SetProperty(IDeserializerNode target, PropertySpec property, object propertyValue) { if (!property.IsWritable) { throw new InvalidOperationException("Unable to set property."); } if (typeof(IClientRepository).IsAssignableFrom(property.PropertyType)) { var repoImplementationType = this.clientRepositoryImplementationMap.GetOrAdd(property.PropertyType, t => t.Assembly.GetTypes() .First( x => !x.IsInterface && x.IsClass && t .IsAssignableFrom (x))); var listProxyValue = propertyValue as LazyCollectionProxy; object repo; if (listProxyValue != null) { repo = Activator.CreateInstance(repoImplementationType, this.client, listProxyValue.Uri, null, target.Value); } else { repo = Activator.CreateInstance(repoImplementationType, this.client, target.Uri + "/" + NameUtils.ConvertCamelCaseToUri(property.Name), propertyValue, target.Value); } property.SetValue(target.Value, repo); return; } property.SetValue(target.Value, propertyValue); }
private void DeserializeArrayNode(IDeserializerNode node, Reader reader) { if (TryDeserializeAsReference(node, reader)) { return; } TypeSpec elementType; if (node.ExpectedBaseType != null && node.ExpectedBaseType.IsCollection) { elementType = node.ExpectedBaseType.ElementType; } else { elementType = node.Context.GetClassMapping(typeof(object)); } deserializeArrayNodeGenericMethod(elementType, this, node, reader); }
private void DeserializeValueNode(IDeserializerNode node, Reader reader) { if (reader.Token.Type == JTokenType.Object) { var jobj = reader.Token as JObject; JToken typeNameToken; if (!jobj.TryGetValue("_type", out typeNameToken)) { throw new PomonaSerializationException( "Trying to deserialize boxed value, but lacks _type property."); } JToken valueToken; if (!jobj.TryGetValue("value", out valueToken)) { throw new PomonaSerializationException( "Trying to deserialize boxed value, but lacks value property."); } var typeName = typeNameToken.ToString(); node.SetValueType(typeName); node.Value = valueToken.ToObject(node.ValueType.Type, this.jsonSerializer); } else { var converter = node.ValueType.GetCustomJsonConverter(); if (converter == null) { node.Value = reader.Token.ToObject(node.ValueType.Type, this.jsonSerializer); } else { node.Value = converter.ReadJson(new JTokenReader(reader.Token), node.ValueType.Type, null, this.jsonSerializer); } } }
public void OnMissingRequiredPropertyError(IDeserializerNode node, PropertySpec targetProp) { }
private void DeserializeNode(IDeserializerNode node, Reader reader) { if (reader.Token.Type == JTokenType.Null) { if (node.ExpectedBaseType != null && node.ExpectedBaseType.Type.IsValueType && !node.ExpectedBaseType.IsNullable) { throw new PomonaSerializationException("Deserialized to null, which is not allowed value for casting to type " + node.ValueType.FullName); } node.Value = null; return; } TypeSpec mappedType; if (node.ExpectedBaseType != null && node.ExpectedBaseType != typeof(object)) { if (SetNodeValueType(node, reader.Token)) { mappedType = node.ValueType; } else { mappedType = node.ExpectedBaseType; } } else if (reader.Token.Type == JTokenType.String) { node.SetValueType(node.Context.GetClassMapping(typeof(string))); mappedType = node.ValueType; } else { if (!SetNodeValueType(node, reader.Token)) { throw new PomonaSerializationException( "No expected type to deserialize to provided, and unable to get type from incoming JSON."); } mappedType = node.ValueType; } switch (mappedType.SerializationMode) { case TypeSerializationMode.Structured: DeserializeComplexNode(node, reader); break; case TypeSerializationMode.Value: DeserializeValueNode(node, reader); break; case TypeSerializationMode.Array: DeserializeArrayNode(node, reader); break; case TypeSerializationMode.Dictionary: DeserializeDictionary(node, reader); break; default: throw new NotImplementedException("Don't know how to deserialize node with mode " + mappedType.SerializationMode); } }
private void DeserializeThroughContext(IDeserializerNode node, Reader reader) { node.Context.Deserialize(node, n => DeserializeNode(n, reader)); }
public object CreateReference(IDeserializerNode node) { return(this.resourceResolver.ResolveUri(node.Uri)); }
private void DeserializeArrayNodeGeneric <TElement>(IDeserializerNode node, Reader reader) { if (TryDeserializeAsReference(node, reader)) { return; } var jarr = reader.Token as JArray; if (jarr == null) { throw new PomonaSerializationException("Expected JSON token of type array, but was " + reader.Token.Type); } var expectedBaseType = node.ExpectedBaseType; // Deserialize as object array by default bool asArray; TypeSpec elementType; if (expectedBaseType != null && expectedBaseType.IsCollection) { elementType = expectedBaseType.ElementType; asArray = expectedBaseType.IsArray; } else { elementType = node.Context.GetClassMapping(typeof(object)); asArray = true; } bool isPatching; ICollection <TElement> collection; if (node.Value == null) { if (expectedBaseType != null && expectedBaseType == typeof(ISet <TElement>)) { collection = new HashSet <TElement>(); } else { collection = new List <TElement>(); } isPatching = false; } else { collection = (ICollection <TElement>)node.Value; isPatching = true; } if (isPatching && node.Operation == DeserializerNodeOperation.Post) { // Clear list and add new items node.CheckItemAccessRights(HttpMethod.Delete); collection.Clear(); } foreach (var jitem in jarr) { var jobj = jitem as JObject; var itemNode = new ItemValueDeserializerNode(elementType, node.Context, node.ExpandPath, node); if (jobj != null) { foreach (var jprop in jobj.Properties().Where(IsIdentifierProperty)) { // Starts with "-@" or "*@" var identifyPropName = jprop.Name.Substring(2); var identifyProp = itemNode.ValueType.Properties.FirstOrDefault(x => x.JsonName == identifyPropName); if (identifyProp == null) { throw new PomonaSerializationException("Unable to find predicate property " + jprop.Name + " in object"); } var identifierNode = new ItemValueDeserializerNode(identifyProp.PropertyType, itemNode.Context, parent: itemNode); DeserializeThroughContext(identifierNode, new Reader(jprop.Value)); var identifierValue = identifierNode.Value; if (jprop.Name[0] == '-') { itemNode.Operation = DeserializerNodeOperation.Delete; } else if (jprop.Name[0] == '*') { itemNode.Operation = DeserializerNodeOperation.Patch; } else { throw new PomonaSerializationException("Unexpected json patch identifier property."); } itemNode.Value = collection.Cast <object>().First( x => identifierValue.Equals(identifyProp.GetValue(x, itemNode.Context))); } } if (itemNode.Operation == DeserializerNodeOperation.Delete) { node.CheckItemAccessRights(HttpMethod.Delete); collection.Remove((TElement)itemNode.Value); } else { if (itemNode.Operation == DeserializerNodeOperation.Patch) { node.CheckItemAccessRights(HttpMethod.Patch); } else if (isPatching) { node.CheckAccessRights(HttpMethod.Post); } DeserializeThroughContext(itemNode, new Reader(jitem)); if (itemNode.Operation != DeserializerNodeOperation.Patch) { if (!(itemNode.ExpectedBaseType is StructuredType) || itemNode.ExpectedBaseType.IsAnonymous() || !collection.Contains((TElement)itemNode.Value)) { collection.Add((TElement)itemNode.Value); } } } } if (node.Value == null) { node.Value = asArray ? collection.ToArray() : collection; } }
private static bool SetNodeValueType(IDeserializerNode node, JToken jtoken) { var jobj = jtoken as JObject; if (jobj != null) { JToken explicitTypeSpec; if (jobj.TryGetValue("_type", out explicitTypeSpec)) { if (explicitTypeSpec.Type != JTokenType.String) { throw new PomonaSerializationException( "Found _type property on JSON object and expected this to be string, but got " + explicitTypeSpec.Type); } var typeName = explicitTypeSpec.Value <string>(); if (typeName == "__result__") { if (!(node.ExpectedBaseType is QueryResultType) && node.ExpectedBaseType is EnumerableTypeSpec) { Type queryResultGenericTypeDefinition; if (node.ExpectedBaseType.Type.IsGenericInstanceOf(typeof(ISet <>))) { queryResultGenericTypeDefinition = typeof(QuerySetResult <>); } else { queryResultGenericTypeDefinition = typeof(QueryResult <>); } var queryResultTypeInstance = queryResultGenericTypeDefinition.MakeGenericType(node.ExpectedBaseType.ElementType); if (node.ExpectedBaseType.Type.IsAssignableFrom(queryResultTypeInstance)) { node.SetValueType(queryResultTypeInstance); } } } else { node.SetValueType(typeName); } return(true); } } if (node.ExpectedBaseType == null || node.ExpectedBaseType == typeof(object)) { switch (jtoken.Type) { case JTokenType.String: node.SetValueType(typeof(string)); return(true); case JTokenType.Boolean: node.SetValueType(typeof(bool)); return(true); case JTokenType.Array: node.SetValueType(typeof(object[])); return(true); case JTokenType.Object: node.SetValueType(typeof(Dictionary <string, object>)); return(true); default: return(false); } } return(false); }