private static IEnumerable <KeyValuePair <RankedKey, object> > ToRankedKeyValuesUnordered(object o) { var ty = o.GetType(); if (TypeWrap(ty).IsGenericType&& ty.GetGenericTypeDefinition() == typeof(Dictionary <,>)) { var keyType = TypeWrap(ty).GetGenericArguments()[0]; if (keyType != typeof(string)) { // TODO: Should allow them and call `ToString`? throw new NotImplementedException(); } foreach (DictionaryEntry elem in (IDictionary)o) { yield return(new KeyValuePair <RankedKey, object>( new RankedKey { Order = 0, // Dictionary has no order infomation Key = (string)elem.Key, }, elem.Value)); } } else { var fields = TypeWrap(ty).GetFields(); foreach (var field in fields) { var fieldAttr = GetCustomAttribute <JsonFieldAttribute>(field); // TODO: duplication check var elemName = JsonFieldAttribute.FieldName(fieldAttr, field); var elemValue = field.GetValue(o); var fieldIgnoreAttr = GetCustomAttribute <JsonFieldIgnorableAttribute>(field); if (JsonFieldIgnorableAttribute.IsIgnorable(fieldIgnoreAttr, elemValue)) { continue; } yield return(new KeyValuePair <RankedKey, object>( new RankedKey { Order = JsonFieldAttribute.FieldOrder(fieldAttr), Key = elemName, }, elemValue)); } } }
object DeserializeToObject(INode node, NodeKind targetKind, Type targetType, State state, Type tag) { if (targetKind != NodeKind.Object) { var msg = state.CreateNodeConversionFailureMessage(node, targetType); throw new DeserializeFailureException(msg); } if (node is NullNode) { return(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 = 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: return(container); } else { // Mapping to the structure // 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. return(DeserializeValueAs(node, node.Kind, targetType, state, tag)); }