Exemplo n.º 1
0
        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));
                }
            }
        }
Exemplo n.º 2
0
        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));
        }