/// <summary> /// Converts the original value before serialization. If the serialized value is not the type of <typeparamref name="TOriginal"/>, the <paramref name="item"/> will be returned. /// </summary> /// <param name="item">The item to be deserialized.</param> public void SerializationConvert(JsonItem item) { if (item.Value is TOriginal) { item.Value = Convert(item.Name, (TOriginal)item.Value); } }
/// <summary> /// Reverts the serialized value to <typeparamref name="TOriginal"/>. If the serialized value is not the type of <typeparamref name="TSerialized"/>, nothing will be changed. /// </summary> /// <param name="item">The item to be deserialized.</param> public void DeserializationConvert(JsonItem item) { if (item.Value is TSerialized) { item.Value = Revert(item.Name, (TSerialized)item.Value); } }
bool IJsonInterceptor.OnDeserializing(object data, JsonItem item) { if (data is T) { return(OnDeserializing((T)data, item)); } return(false); }
internal string ConvertToJSON(object obj, ReflectionCache cache) { if (cache.CommonType == ComplexType.Dictionary || cache.CommonType == ComplexType.List) { _useGlobalTypes = false; } var cv = cache.Converter; if (cv != null) { var ji = new JsonItem(String.Empty, obj, false); cv.SerializationConvert(ji); if (ReferenceEquals(obj, ji._Value) == false) { obj = ji._Value; } cache = _manager.GetReflectionCache(obj.GetType()); } var m = cache.SerializeMethod; if (m != null) { if (cache.CollectionName != null) { WriteObject(obj); } else { m(this, obj); } } else { WriteValue(obj); } if (_useGlobalTypes && _globalTypes != null && _globalTypes.Count > 0) { var sb = new StringBuilder(); sb.Append("\"" + JsonDict.ExtTypes + "\":{"); var pendingSeparator = false; foreach (var kv in _globalTypes) { sb.Append(pendingSeparator ? ",\"" : "\""); sb.Append(kv.Key); sb.Append("\":\""); sb.Append(ValueConverter.Int32ToString(kv.Value)); sb.Append('\"'); pendingSeparator = true; } sb.Append("},"); _output.Insert(_before, sb.ToString()); } return(_output.ToString()); }
void ConvertObject(IJsonConverter converter, JsonItem ji, Type sourceType) { var rt = converter.GetReversiveType(ji); var xv = ji._Value; if (xv != null && rt != null && sourceType.Equals(xv.GetType()) == false) { var c = _manager.GetReflectionCache(rt); var jt = Reflection.GetJsonDataType(rt); if (jt != JsonDataType.Undefined) { xv = c.DeserializeMethod(this, xv, c); } else if (xv is JsonDict) { xv = CreateObject((JsonDict)xv, c, null); } } ji._Value = xv; converter.DeserializationConvert(ji); }
void ConvertProperty(object o, JsonMemberSetter pi, JsonItem ji) { var pc = pi.Converter ?? pi.Member.MemberTypeReflection.Converter; var rt = pc.GetReversiveType(ji); var xv = ji._Value; if (xv != null && rt != null && pi.Member.MemberType.Equals(xv.GetType()) == false) { var c = _manager.GetReflectionCache(rt); var jt = Reflection.GetJsonDataType(rt); if (jt != JsonDataType.Undefined) { xv = c.DeserializeMethod(this, xv, c); } else if (xv is JsonDict) { xv = CreateObject((JsonDict)xv, c, pi.Member.Getter(o)); } } ji._Value = xv; pc.DeserializationConvert(ji); }
static bool ConvertItems(JsonMemberSetter pi, JsonItem ji) { var vl = ji._Value as IList; var l = vl.Count; var converted = false; var ai = new JsonItem(ji._Name, null, false); for (int i = 0; i < l; i++) { var vi = vl[i]; ai._Value = vi; pi.ItemConverter.DeserializationConvert(ai); if (ReferenceEquals(vi, ai._Value) == false) { vl[i] = ai._Value; converted = true; } } if (converted) { if (pi.Member.JsonDataType == JsonDataType.Array) { ji._Value = Array.CreateInstance(pi.Member.ElementType, l); vl.CopyTo((Array)ji._Value, 0); } else if (pi.Member.JsonDataType == JsonDataType.List) { ji._Value = pi.Member.MemberTypeReflection.Instantiate(); var gl = ji._Value as IList; for (int i = 0; i < l; i++) { gl.Add(vl[i]); } } } return(converted); }
/// <summary> /// Returns the expected type for <paramref name="item"/>. The default implementation returns <typeparamref name="TSerialized"/>. /// </summary> /// <param name="item">The item to be deserialized.</param> /// <returns>The type of <typeparamref name="TSerialized"/>.</returns> public virtual Type GetReversiveType(JsonItem item) { return(_SerializedType); }
public object ToObject(string json, Type type) { object o = new JsonParser(json).Decode(); if (o == null) { return(null); } ReflectionCache c = null; if (type != null) { c = _manager.GetReflectionCache(type); var cv = c.Converter; if (cv != null) { var ji = new JsonItem(String.Empty, o, false); ConvertObject(cv, ji, type); if (ReferenceEquals(ji._Value, o) == false) { return(ji._Value); } if (c.CommonType == ComplexType.Dictionary || c.CommonType == ComplexType.List) { _usingglobals = false; } } else if (c.DeserializeMethod != null) { return(c.DeserializeMethod(this, o, c)); } } else { _usingglobals = _params.UsingGlobalTypes; } var d = o as JsonDict; if (d != null) { if (type != null) { #if !SILVERLIGHT if (c.JsonDataType == JsonDataType.DataSet) { return(CreateDataSet(d)); } if (c.JsonDataType == JsonDataType.DataTable) { return(CreateDataTable(d)); } #endif if (c.CommonType == ComplexType.Dictionary) // deserialize a dictionary { return(RootDictionary(o, c)); } } return(CreateObject(d, c, null)); } var a = o as JsonArray; if (a != null) { if (type != null) { if (c.CommonType == ComplexType.Dictionary) // k/v format { return(RootDictionary(o, c)); } if (c.CommonType == ComplexType.List) // deserialize to generic list { return(RootList(o, c)); } if (c.JsonDataType == JsonDataType.Hashtable) { return(RootHashTable(a)); } if (c.CommonType == ComplexType.Array) { return(CreateArray(a, c)); } } return(a.ToArray()); } if (type != null && o.GetType().Equals(type) == false) { return(ChangeType(o, type)); } return(o); }
/// <summary> /// Deserializes an object. /// </summary> /// <param name="data">The data to be deserialized.</param> /// <param name="type">The reflection cache of the type.</param> /// <param name="input">The data container. If this value is not null, deserialized members will be written to it. If null, new object will be created.</param> /// <returns>The deserialized object.</returns> /// <exception cref="JsonSerializationException">Cannot determine type from <paramref name="data"/>.</exception> internal object CreateObject(JsonDict data, ReflectionCache type, object input) { if (data.RefIndex > 0) { object v = null; _cirrev.TryGetValue(data.RefIndex, out v); return(v); } if (data.Types != null && data.Types.Count > 0) { _usingglobals = true; globaltypes = new Dictionary <string, object> (); foreach (var kv in data.Types) { globaltypes.Add((string)kv.Value, kv.Key); } } var tn = data.Type; bool found = (tn != null && tn.Length > 0); #if !SILVERLIGHT if (found == false && type != null && typeof(object).Equals(type.Type)) { return(data); } #endif if (found) { if (_usingglobals) { object tname = ""; if (globaltypes != null && globaltypes.TryGetValue(data.Type, out tname)) { tn = (string)tname; } } type = _manager.GetReflectionCache(Reflection.Instance.GetTypeFromCache(tn)); } if (type == null) { throw new JsonSerializationException("Cannot determine type"); } object o = input; if (o == null) { o = _params.ParametricConstructorOverride ? System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type.Type) : type.Instantiate(); } int circount = 0; // dictionary lookup makes it impossible to use objects with a custom GetHashCode based on (unchanging) properties: if (_circobj.TryGetValue(o, out circount) == false) { circount = _circobj.Count + 1; _circobj.Add(o, circount); _cirrev.Add(circount, o); } var si = type.Interceptor; if (si != null) { si.OnDeserializing(o); } Dictionary <string, JsonMemberSetter> props = type.Setters; //TODO: Candidate to removal of unknown use of map //if (data.Map != null) { // ProcessMap (o, props, data.Map); //} foreach (var kv in data) { var n = kv.Key; var v = kv.Value; JsonMemberSetter pi; if (props.TryGetValue(n, out pi) == false || pi.CanWrite == false && pi.Member.JsonDataType != JsonDataType.List) { continue; } MemberCache m = pi.Member; var ji = new JsonItem(n, v, false); bool converted = false; // TODO: Convert items for types implements IEnumerable and Add(?) method if (v is IList && pi.ItemConverter != null) { converted = ConvertItems(pi, ji); } if (pi.Converter != null || m.MemberTypeReflection.Converter != null) { ConvertProperty(o, pi, ji); } object oset = null; // use the converted value if (converted || ReferenceEquals(ji._Value, v) == false) { if (pi.CanWrite == false && m.JsonDataType == JsonDataType.List) { ji._Value = CreateList((JsonArray)ji._Value, m.MemberTypeReflection, m.Getter(o)); } if (ji._Value != null || m.IsClass || m.IsNullable) { oset = ji._Value; goto SET_VALUE; } continue; } // process null value if (ji._Value == null) { var i = new JsonItem(n, null, false); if (si != null && si.OnDeserializing(o, i) == false) { continue; } if (i.Value != null || m.IsClass || m.IsNullable) { o = m.Setter(o, i.Value); } continue; } v = ji._Value; // set member value switch (m.JsonDataType) { case JsonDataType.Undefined: goto default; case JsonDataType.Int: oset = (int)(long)v; break; case JsonDataType.String: case JsonDataType.Bool: case JsonDataType.Long: oset = v; break; case JsonDataType.Double: oset = v is long?(double)(long)v : (double)v; break; case JsonDataType.Single: oset = v is long?(float)(long)v : (float)(double)v; break; case JsonDataType.DateTime: oset = CreateDateTime(this, v); break; case JsonDataType.Guid: oset = CreateGuid(v); break; case JsonDataType.ByteArray: oset = Convert.FromBase64String((string)v); break; case JsonDataType.List: if (m.MemberTypeReflection.CollectionName != null) { goto default; } oset = CreateList((JsonArray)v, m.MemberTypeReflection, pi.CanWrite && (m.IsClass || m.IsStruct) ? null : m.Getter(o)); break; case JsonDataType.Object: oset = v; break; default: if (m.DeserializeMethod != null) { oset = m.MemberTypeReflection.DeserializeMethod(this, ji._Value, m.MemberTypeReflection); goto SET_VALUE; } if ((m.IsClass || m.IsStruct) && v is JsonDict) { oset = CreateObject((JsonDict)v, m.MemberTypeReflection, m.Getter(o)); } else if (v is JsonArray) { oset = CreateArray((JsonArray)v, _manager.GetReflectionCache(typeof(object[]))); } else if (m.IsValueType) { oset = ChangeType(v, m.ChangeType); } else { oset = v; } break; } SET_VALUE: ji.Value = oset; if (si != null) { if (si.OnDeserializing(o, ji) == false) { continue; } } if (m.Setter != null) { o = m.Setter(o, ji.Value); } } if (si != null) { si.OnDeserialized(o); } return(o); }
// HACK: This is a very long function, individual parts in regions are made inline for better performance void WriteObject(object obj) { #region Detect Circular Reference var ci = 0; if (_cirobj.TryGetValue(obj, out ci) == false) { _cirobj.Add(obj, _cirobj.Count + 1); } else { if (_currentDepth > 0 && _useExtensions && _params.InlineCircularReferences == false) { //_circular = true; _output.Append("{\"" + JsonDict.ExtRefIndex + "\":"); _output.Append(ValueConverter.Int32ToString(ci)); _output.Append("}"); return; } } #endregion var def = _manager.GetReflectionCache(obj.GetType()); var si = def.Interceptor; if (si != null && si.OnSerializing(obj) == false) { return; } #region Locate Extension Insertion Position if (_useGlobalTypes == false) { _output.Append('{'); } else { if (_before == 0) { _output.Append('{'); _before = _output.Length; } else { _output.Append('{'); } } #endregion _currentDepth++; if (_currentDepth > _maxDepth) { throw new JsonSerializationException("Serializer encountered maximum depth of " + _maxDepth); } //var map = new Dictionary<string, string> (); var append = false; #region Write Type Reference if (_useExtensions) { if (_useGlobalTypes == false) { WritePairFast(JsonDict.ExtType, def.AssemblyName); } else { var dt = 0; var ct = def.AssemblyName; if (_globalTypes.TryGetValue(ct, out dt) == false) { dt = _globalTypes.Count + 1; _globalTypes.Add(ct, dt); } WritePairFast(JsonDict.ExtType, ValueConverter.Int32ToString(dt)); } append = true; } #endregion var g = def.Getters; var c = g.Length; for (int ii = 0; ii < c; ii++) { var p = g[ii]; var m = p.Member; #region Skip Members Not For Serialization if (p.Serializable == TriState.False) { continue; } if (p.Serializable == TriState.Default) { if (m.IsStatic && _params.SerializeStaticMembers == false || m.IsReadOnly && m.MemberTypeReflection.AppendItem == null && (m.IsProperty && _showReadOnlyProperties == false || m.IsProperty == false && _showReadOnlyFields == false)) { continue; } } #endregion var ji = new JsonItem(m.MemberName, m.Getter(obj), true); if (si != null && si.OnSerializing(obj, ji) == false) { continue; } var cv = p.Converter ?? m.MemberTypeReflection.Converter; if (cv != null) { cv.SerializationConvert(ji); } #region Convert Items if (p.ItemConverter != null) { var ev = ji._Value as IEnumerable; if (ev != null) { var ai = new JsonItem(ji.Name, null, false); var ol = new List <object> (); foreach (var item in ev) { ai.Value = item; p.ItemConverter.SerializationConvert(ai); ol.Add(ai.Value); } ji._Value = ol; } } #endregion #region Determine Serialized Field Name if (p.SpecificName) { if (ji._Value == null || p.TypedNames == null || p.TypedNames.TryGetValue(ji._Value.GetType(), out ji._Name) == false) { ji._Name = p.SerializedName; } } else { ji._Name = p.SerializedName; } #endregion #region Skip Null, Default Value or Empty Collection if (_params.SerializeNullValues == false && (ji._Value == null || ji._Value is DBNull)) { continue; } if (p.HasNonSerializedValue && Array.IndexOf(p.NonSerializedValues, ji._Value) != -1) { // ignore fields with default value continue; } if (m.IsCollection && _params.SerializeEmptyCollections == false) { var vc = ji._Value as ICollection; if (vc != null && vc.Count == 0) { continue; } } #endregion if (append) { _output.Append(','); } #region Write Name if (p.SpecificName) { WriteStringFast(ji._Name); _output.Append(':'); } else { _naming.WriteName(_output, ji._Name); } #endregion #region Write Value if (m.SerializeMethod != null && cv == null) { var v = ji._Value; if (v == null || v is DBNull) { _output.Append("null"); } else if (m.MemberTypeReflection.CollectionName != null) { WriteObject(v); } else { m.SerializeMethod(this, v); } } else { WriteValue(ji._Value); } #endregion append = true; } #region Write Inherited Collection if (def.CollectionName != null && def.SerializeMethod != null) { if (append) { _output.Append(','); } WriteStringFast(def.CollectionName); _output.Append(':'); def.SerializeMethod(this, obj); append = true; } #endregion #region Write Extra Values if (si != null) { var ev = si.SerializeExtraValues(obj); if (ev != null) { foreach (var item in ev) { if (append) { _output.Append(','); } WritePair(item._Name, item._Value); append = true; } } si.OnSerialized(obj); } #endregion _currentDepth--; _output.Append('}'); }
/// <summary> /// This method is called before deserializing a field or a property. If the method returns false, the member will not be deserialized. /// </summary> /// <param name="data">The container object.</param> /// <param name="item">The item to be deserialized.</param> /// <returns>Whether the member should be deserialized.</returns> public virtual bool OnDeserializing(T data, JsonItem item) { return(true); }