object DeserializeToBoolean(INode node, NodeKindWrapped targetKind, Type targetType, State state, Type tag) { if (node is NullNode) { if (!TypeHelper.IsBoxed(targetType)) { var msg = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg); } return(targetKind.Wrapped ? NullNode.Null : null); } var bNode = node as BooleanNode; if (bNode != null) { return(targetKind.Wrapped ? node : CreateInstanceIfConstrucutable <bool>(targetType, bNode.Value, state)); } var msg0 = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg0); }
object DeserializeValueAs(INode node, NodeKindWrapped targetKind, Type targetType, State state, Type tag) { switch (targetKind.Kind) { case NodeKind.Boolean: return(DeserializeToBoolean(node, targetKind, targetType, state, tag)); case NodeKind.Integer: case NodeKind.Float: return(DeserializeToNumber(node, targetKind, targetType, state, tag)); case NodeKind.String: return(DeserializeToString(node, targetKind, targetType, state, tag)); case NodeKind.Array: return(DeserializeToArray(node, targetKind, targetType, state, tag)); case NodeKind.Object: return(DeserializeToObject(node, targetKind, targetType, state, tag)); case NodeKind.Null: return(DeserializeToNull(node, targetKind, targetType, state, tag)); default: throw new NotImplementedException("Unmatched kind: " + targetKind.Kind); } }
object DeserializeToNull(INode node, NodeKindWrapped targetKind, Type targetType, State state, Type tag) { if (node is NullNode) { // TODO: type check of targetType return(targetKind.Wrapped ? NullNode.Null : null); } // TODO: Should raise error? throw new NotImplementedException(); }
object DeserializeToNumber(INode node, NodeKindWrapped targetKind, Type targetType, State state, Type tag) { if (node is NullNode) { if (!TypeHelper.IsBoxed(targetType)) { var msg = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg); } return(targetKind.Wrapped ? NullNode.Null : null); } var iNode = node as IntegerNode; if (iNode != null) { return(targetKind.Wrapped ? node : CreateInstanceIfConstrucutable <long>(targetType, iNode.Value, state)); } var fNode = node as FloatNode; if (fNode != null) { return(targetKind.Wrapped ? node : CreateInstanceIfConstrucutable <double>(targetType, fNode.Value, state)); } var msg0 = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg0); }
object DeserializeToObject(INode node, NodeKindWrapped targetKind, Type targetType, State state, Type tag) { if (targetKind.Kind != NodeKind.Object) { var msg = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg); } if (node is NullNode) { return(targetKind.Wrapped ? NullNode.Null : null); } var oNode = node as ObjectNode; if (oNode != null) { bool asDictionary = targetType == typeof(object) || (TypeHelper.TypeWrap(targetType).IsGenericType&& targetType.GetGenericTypeDefinition() == typeof(Dictionary <,>)) ; if (asDictionary) { // To Dictionary Type containerTy = targetType; if (containerTy == typeof(object)) { containerTy = targetKind.Wrapped ? typeof(Dictionary <string, INode>) : typeof(Dictionary <string, object>); } var keyType = TypeHelper.TypeWrap(containerTy).GetGenericArguments()[0]; if (keyType != typeof(string)) { throw new NotImplementedException(); } var container = (IDictionary)Activator.CreateInstance(containerTy); if (oNode.Elems == null) { goto dictionaryDecoded; } var allElemType = TypeHelper.TypeWrap(containerTy).GetGenericArguments()[1]; foreach (var elem in oNode.Elems) { var elemType = allElemType; if (tag != null) { Type typeForKey; if (DynamicResolver.Find(tag, elem.Key, out typeForKey)) { elemType = typeForKey; } } // TODO: duplication check var v = DeserializeValue(elem.Value, elemType, state.NestAsElem(elem.Key), tag); container.Add(elem.Key, v); } dictionaryDecoded: if (targetKind.Wrapped) { return(new ObjectNode(container as Dictionary <string, INode>)); } else { return(container); } } else { // Mapping to the structure (class | struct) // TODO: add type check var container = Activator.CreateInstance(targetType); var fields = TypeHelper.TypeWrap(targetType).GetFields(); foreach (var field in fields) { var attr = TypeHelper.GetCustomAttribute <JsonFieldAttribute>(field); // TODO: duplication check var elemName = JsonFieldAttribute.FieldName(attr, field); INode elem = null; if (oNode.Elems == null || !oNode.Elems.TryGetValue(elemName, out elem)) { // TODO: ignore or raise errors? continue; } var elemState = state.NestAsElem(elemName); if (attr != null && attr.TypeHints != null) { bool resolved = false; foreach (var hint in attr.TypeHints) { var elemType = hint; try { var v = DeserializeValue(elem, elemType, elemState, tag); field.SetValue(container, v); resolved = true; break; } catch (Exception) { } } if (!resolved) { var msg = elemState.CreateNodeConversionFailureMessage(elem, attr.TypeHints); throw new DeserializeFailureException(msg); } } else { var elemType = field.FieldType; var elemTag = tag; if (attr != null && attr.DynamicResolverTag != null) { if (!TypeHelper.TypeWrap(elemType).IsGenericType || elemType.GetGenericTypeDefinition() != typeof(Dictionary <,>)) { var baseMsg = "A type of the field which has DynamicResolver must be a Dictionary<,>"; var msg = elemState.CreateMessage("{0}: Type = {1}", baseMsg, elemType); throw new DeserializeFailureException(msg); } var keyType = TypeHelper.TypeWrap(elemType).GetGenericArguments()[0]; if (keyType != typeof(string)) { var baseMsg = "A key of the dictionary which has DynamicResolver must be a string type"; var msg = elemState.CreateMessage("{0}: KeyType = {1}", baseMsg, keyType); throw new DeserializeFailureException(msg); } elemTag = attr.DynamicResolverTag; } var v = DeserializeValue(elem, elemType, elemState, elemTag); field.SetValue(container, v); } } return(container); } } // A json node type is NOT an object but the target type is an object. // Thus, change a target kind and retry. var nodeKindWrapped = new NodeKindWrapped { Kind = node.Kind, Wrapped = targetKind.Wrapped, }; if (targetKind.Wrapped) { targetType = Node.ValueTypeOfKind(node.Kind); } return(DeserializeValueAs(node, nodeKindWrapped, targetType, state, tag)); }
object DeserializeToArray(INode node, NodeKindWrapped targetKind, Type targetType, State state, Type tag) { bool isConvertible = targetType == typeof(object) || (targetType.IsArray) || (TypeHelper.TypeWrap(targetType).IsGenericType&& targetType.GetGenericTypeDefinition() == typeof(List <>)) ; if (!isConvertible) { var msg = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg); } if (node is NullNode) { return(targetKind.Wrapped ? NullNode.Null : null); } var aNode = node as ArrayNode; if (aNode != null) { if (targetType.IsArray || targetType == typeof(object)) { // To Array var conteinerTy = targetType; if (conteinerTy == typeof(object)) { conteinerTy = typeof(object[]); } var len = aNode.Elems != null ? aNode.Elems.Count : 0; var container = (Array)Activator.CreateInstance(conteinerTy, new object[] { len }); var elemType = conteinerTy.GetElementType(); for (int i = 0; i < len; ++i) { var v = DeserializeValue(aNode.Elems[i], elemType, state.NestAsElem(i), tag); container.SetValue(v, i); } return(container); } else { // To List var conteinerTy = targetType; var len = aNode.Elems != null ? aNode.Elems.Count : 0; var container = (IList)Activator.CreateInstance(conteinerTy); var elemType = TypeHelper.TypeWrap(conteinerTy).GetGenericArguments()[0]; for (int i = 0; i < len; ++i) { var v = DeserializeValue(aNode.Elems[i], elemType, state.NestAsElem(i), tag); container.Add(v); } if (targetKind.Wrapped) { return(new ArrayNode(container as List <INode>)); } else { return(container); } } } var msg0 = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg0); }