/// <summary> /// get json key of a property /// </summary> /// <param name="property">name of property</param> /// <returns>name of key</returns> public static string GetKey(PropertyInfo property) { #if WINDOWS_UWP JsonKeyAttribute attribute = property.GetCustomAttribute <JsonKeyAttribute>(); #else JsonKeyAttribute attribute = GetCustomAttribute(property, typeof(JsonKeyAttribute)) as JsonKeyAttribute; #endif return(attribute?.Key); }
/// <summary> /// reads a type from a json node /// </summary> /// <param name="type">type to read</param> /// <param name="node">json node</param> /// <param name="variant"></param> /// <returns>instance with data from json node</returns> object Read(Type type, JsonNode node, bool variant) { if (node is JsonValue && ((JsonValue)node).Value == null) { return(null); } if (type == typeof(object)) { if (!(node is JsonValue)) { throw new JsonException("Currently only values are supported for object properties"); } return(((JsonValue)node).Value); } if (type.IsArray) { if (type.GetElementType() == typeof(byte)) { if (!(node is JsonValue)) { throw new JsonException("Unable to read value from non value node"); } string base64value = ((JsonValue)node).Value as string; if (base64value == null) { return(null); } return(Convert.FromBase64String(base64value)); } if (!(node is JsonArray)) { throw new JsonException("Unable to read array from non array json node"); } return(ReadArray(type.GetElementType(), (JsonArray)node, variant)); } #if WINDOWS_UWP if (type.GetTypeInfo().IsValueType || type.GetTypeInfo().IsEnum || type == typeof(string) || type == typeof(Version)) { #else if (type.IsValueType || type.IsEnum || type == typeof(string) || type == typeof(Version) || type == typeof(IntPtr) || type == typeof(UIntPtr)) { #endif if (!(node is JsonValue)) { throw new JsonException("Unable to read value from non value node"); } return(Converter.Convert(((JsonValue)node).Value, type)); } if (type == typeof(Type)) { return(Type.GetType(node.SelectValue <string>())); } // check for variant types if (variant) { Type customtype = node.SelectValue <Type>("type"); return(Read(customtype, node.SelectNode("data"))); } if (serializers.Contains(type)) { return(serializers.Get(type).Deserialize(node)); } if (!(node is JsonObject)) { throw new JsonException("Unable to read object from non object node"); } JsonObject @object = (JsonObject)node; #if WINDOWS_UWP object instance = Activator.CreateInstance(type); #else object instance = Activator.CreateInstance(type, true); #endif foreach (PropertyInfo property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (!property.CanWrite) { continue; } string key = JsonKeyAttribute.GetKey(property) ?? property.Name.ToLower(); if ([email protected](key)) { continue; } string loader = JsonLoaderAttribute.Get(property); object value; if (loader != null) { MethodInfo method = type.GetMethod(loader, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); value = method.Invoke(null, new object[] { @object.SelectValue <string>(key) }); } else { value = Read(property.PropertyType, @object.GetNode(key), VariantAttribute.IsVariant(property)); } try { property.SetValue(instance, Converter.Convert(value, property.PropertyType), null); } catch (Exception e) { // TODO: log this shit } } return(instance); } object ReadArray(Type elementtype, JsonArray node, bool variant) { Array instance = Array.CreateInstance(elementtype, node.Count); for (int i = 0; i < node.Count; ++i) { instance.SetValue(Read(elementtype, node.GetNode(i), variant), i); } return(instance); }
/// <summary> /// writes an object to a json structure /// </summary> /// <param name="object"></param> /// <param name="variant"></param> /// <returns></returns> JsonNode Write(object @object, bool variant) { if (@object is Array) { if (@object.GetType().GetElementType() == typeof(byte)) { return(new JsonValue(Convert.ToBase64String((byte[])@object))); } return(WriteArray((Array)@object, variant)); } if (@object is IDictionary) { JsonObject dictionary = new JsonObject(); foreach (object kvp in ((IDictionary)@object).Keys) { dictionary[kvp.ToString()] = Write(((IDictionary)@object)[kvp]); } return(dictionary); } #if WINDOWS_UWP if (@object == null || @object is string || @object.GetType().GetTypeInfo().IsEnum || @object.GetType().GetTypeInfo().IsValueType || @object is Version) #else if (@object == null || @object is string || @object.GetType().IsEnum || @object.GetType().IsValueType || @object is Version || @object is IntPtr || @object is UIntPtr) #endif { return(new JsonValue(@object)); } if (@object is Type type) { return(new JsonValue(type.AssemblyQualifiedName)); } // check for variant types if (variant) { JsonObject jsonobject = new JsonObject { ["type"] = Write(@object.GetType()), ["data"] = Write(@object) }; return(jsonobject); } if (serializers.Contains(@object.GetType())) { return(serializers.Get(@object.GetType()).Serialize(@object)); } JsonObject json = new JsonObject(); foreach (PropertyInfo property in @object.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { // currently not sure ... perhaps optional deactivation //if(!property.CanWrite) // continue; // ignore indexers if (property.GetIndexParameters().Length > 0) { continue; } string key = JsonKeyAttribute.GetKey(property) ?? property.Name.ToLower(); json[key] = Write( #if FRAMEWORK35 property.GetValue(@object, null), #else property.GetValue(@object), #endif VariantAttribute.IsVariant(property)); } return(json); }