bool IJsonInterceptor.OnDeserializing(object data, JsonItem item) { if (data is T) { return(OnDeserializing((T)data, item)); } return(false); }
void ConvertProperty(object o, JsonMemberSetter pi, JsonItem ji) { var pc = pi.Converter ?? pi.TypeInfo.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.GetSerializationInfo(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 = pc.DeserializationConvert(xv); }
// HACK: This is a very long function, individual parts in regions are made inline for better performance internal void WriteObject(object obj, SerializationInfo info) { var def = info ?? _manager.GetSerializationInfo(obj.GetType()); #region Detect Circular Reference if (def.Reflection.CircularReferencable) { var ci = 0; if (_cirobj == null) { _cirobj = new Dictionary <object, int> (); } if (_cirobj.TryGetValue(obj, out ci) == false) { _cirobj.Add(obj, _cirobj.Count + 1); } else { if (_currentDepth > 0 && _useExtensions && _manager.InlineCircularReferences == false) { //_circular = true; OutputText("{\"" + JsonDict.ExtRefIndex + "\":"); OutputText(ValueConverter.Int32ToString(ci)); OutputChar('}'); return; } } } #endregion var si = def.Interceptor; if (si != null && si.OnSerializing(obj) == false) { return; } OutputChar('{'); _currentDepth++; if (_currentDepth > _maxDepth) { throw new JsonSerializationException("Serializer encountered maximum depth of " + _maxDepth + ". Last object name on stack: " + def.Reflection.AssemblyName); } var append = false; #region Write Type Reference if (def.Reflection.IsAbstract || def.Alias != null) { WritePairFast(JsonDict.ExtType, def.Alias ?? def.Reflection.TypeName); append = true; } else if (_useExtensions && info == null && def.Reflection.IsAnonymous == false || def.Reflection.Type.Equals(obj.GetType()) == false) { WritePairFast(JsonDict.ExtType, def.Reflection.TypeName); 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 && _manager.SerializeStaticMembers == false || m.IsReadOnly && p.TypeInfo.Reflection.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 ?? p.TypeInfo.Converter; if (cv != null) { ji._Value = cv.SerializationConvert(ji._Value); } #region Convert Items var ic = p.ItemConverter; if (ic == null && p.TypeInfo.TypeParameters != null && p.Member.IsNullable == false) { var it = p.TypeInfo.TypeParameters[0]; // item type ic = it.Converter; } if (ic != null) { var ev = ji._Value as IEnumerable; if (ev != null) { var ol = new List <object> (); foreach (var item in ev) { ol.Add(ic.SerializationConvert(item)); } 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 (_manager.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 && _manager.SerializeEmptyCollections == false) { var vc = ji._Value as ICollection; if (vc != null && vc.Count == 0) { continue; } } #endregion if (append) { OutputChar(','); } #region Write Name if (p.SpecificName) { WriteStringFast(ji._Name); OutputChar(':'); } else { OutputName(ji._Name); } #endregion #region Write Value if (p.SerializeMethod != null && cv == null) { var v = ji._Value; if (v == null || v is DBNull) { OutputText("null"); } else if (p.TypeInfo.CollectionName != null) { WriteObject(v, p.TypeInfo); } else { p.SerializeMethod(this, v); } } else { WriteValue(ji._Value); } #endregion append = true; } #region Write Inherited Collection if (def.CollectionName != null && def.SerializeMethod != null) { if (append) { OutputChar(','); } WriteStringFast(def.CollectionName); OutputChar(':'); 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) { OutputChar(','); } WriteField(item._Name, item._Value); append = true; } } si.OnSerialized(obj); } #endregion _currentDepth--; OutputChar('}'); }
/// <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); }
/// <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); }
object CreateList(JsonArray data, SerializationInfo info, object input) { var listType = info; var ec = listType.TypeParameters != null ? listType.TypeParameters[0] : null; var r = listType.ItemDeserializeMethod; var ic = ec.Converter; object l = input ?? info.Instantiate(); IList col = l as IList; if (col != null) { if (ic != null) { Type rt = null; foreach (var item in data) { if (rt == null) { var ji = new JsonItem(null, item); rt = ic.GetReversiveType(ji); } var xv = item; if (xv != null && rt != null && ec.Reflection.Type.Equals(xv.GetType()) == false) { xv = RevertValueType(rt, xv); } xv = ic.DeserializationConvert(xv); if (xv == null) { continue; } // TODO: determine whether item type is nullable col.Add(xv != null ? r(this, xv, ec) : null); } return(col); } else if (r != null) { foreach (var item in data) { // TODO: determine whether item type is nullable col.Add(item != null ? r(this, item, ec) : null); } return(col); } } var a = listType.Reflection.AppendItem; if (a != null) { if (l == null) { throw new JsonSerializationException("The collection member typed \"" + listType.Reflection.AssemblyName + "\" was null and could not be instantiated"); } if (ic != null) { Type rt = null; foreach (var item in data) { if (rt == null) { var ji = new JsonItem(null, item); rt = ic.GetReversiveType(ji); } var xv = item; if (xv != null && rt != null && ec.Reflection.Type.Equals(xv.GetType()) == false) { xv = RevertValueType(rt, xv); } xv = ic.DeserializationConvert(xv); if (xv == null) { continue; } a(l, r(this, item, ec)); } } else { foreach (var item in data) { a(l, r(this, item, ec)); } } return(l); } return(col); }
object CreateArray(JsonArray data, SerializationInfo arrayType) { var l = data.Count; var ec = arrayType.TypeParameters[0]; Array col = Array.CreateInstance(ec.Reflection.Type, l); var r = arrayType.ItemDeserializeMethod; var ic = ec.Converter; if (r != null) { if (ic == null) { for (int i = 0; i < l; i++) { var ob = data[i]; if (ob == null) { continue; } col.SetValue(r(this, ob, ec), i); } } else { Type rt = null; for (int i = 0; i < l; i++) { var ob = data[i]; var ji = new JsonItem(null, ob); if (rt == null) { rt = ic.GetReversiveType(ji); } var xv = ob; if (xv != null && rt != null && ec.Reflection.Type.Equals(xv.GetType()) == false) { xv = RevertValueType(rt, xv); } ob = ic.DeserializationConvert(xv); if (ob == null) { continue; } col.SetValue(r(this, ob, ec), i); } } return(col); } // TODO: candidate of code clean-up // create an array of objects for (int i = 0; i < l; i++) { var ob = data[i]; if (ob == null) { continue; } if (ob is IDictionary) { col.SetValue(CreateObject((JsonDict)ob, ec, null), i); } // support jagged array else if (ob is ICollection) { col.SetValue(CreateArray((JsonArray)ob, ec), i); } else { col.SetValue(ChangeType(ob, ec.Reflection.Type), i); } } return(col); }
/// <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, SerializationInfo type, object input) { if (data.RefIndex > 0) { object v = null; _cirrev.TryGetValue(data.RefIndex, out v); return(v); } if (String.IsNullOrEmpty(data.Type) == false) { type = _manager.GetSerializationInfo(data.Type); if (type == null) { type = _manager.GetSerializationInfo(Reflection.GetTypeFromCache(data.Type)); } } if (type != null && typeof(object).Equals(type.Reflection.Type)) { return(data); } if (type == null) { throw new JsonSerializationException("Cannot determine type"); } object o = input; if (o == null) { o = _manager.ParametricConstructorOverride ? System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type.Reflection.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); } var props = type.Setters; foreach (var kv in data) { var n = kv.Key; var v = kv.Value; JsonMemberSetter pi; // field name is not defined if (props.TryGetValue(n, out pi) == false) { continue; } if (pi.CanWrite == false && pi.Member.JsonDataType != JsonDataType.List) { continue; } var 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) { ji._Value = ConvertItems(pi, v as IList); } if (pi.Converter != null || pi.TypeInfo.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, pi.TypeInfo, 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 = v is long?(int)(long)v : v is double?(int)(double)v : v is string?ValueConverter.ToInt32((string)v) : v is bool && (bool)v ? 1 : 0; break; case JsonDataType.String: oset = v is string?(string)v: v is double?((double)v).ToString() : v is long?ValueConverter.Int64ToString((long)v) : v is bool?((bool)v).ToString() : null; break; case JsonDataType.Bool: oset = v is bool?(bool)v : v is double?(double)v != 0 : v is long?(long)v != 0 : v is string?ValueConverter.ToBoolean((string)v) : false; break; case JsonDataType.Long: oset = v is long?(long)v : v is double?(long)(double)v : v is string?ValueConverter.ToInt64((string)v) : v is bool && (bool)v ? 1L : 0L; break; case JsonDataType.Double: oset = v is double?(double)v: v is long?(double)(long)v : v is string?ValueConverter.ToDouble((string)v) : v is bool && (bool)v ? 1D : 0D; break; case JsonDataType.Single: oset = v is double?(float)(double)v: v is long?(float)(long)v : v is string?ValueConverter.ToSingle((string)v) : v is bool && (bool)v ? 1F : 0F; 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 (pi.TypeInfo.CollectionName != null) { goto default; } oset = CreateList((JsonArray)v, pi.TypeInfo, pi.CanWrite && (m.IsClass || m.IsStruct) ? null : m.Getter(o)); break; case JsonDataType.Object: oset = v; break; default: if (pi.TypeInfo.DeserializeMethod != null) { oset = pi.TypeInfo.DeserializeMethod(this, ji._Value, pi.TypeInfo); goto SET_VALUE; } if ((m.IsClass || m.IsStruct) && v is JsonDict) { oset = CreateObject((JsonDict)v, pi.TypeInfo, m.Getter(o)); } else if (v is JsonArray) { oset = CreateArray((JsonArray)v, _manager.GetSerializationInfo(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) { //try { o = m.Setter(o, ji.Value); //} //catch (InvalidCastException) { // if (_manager.SetDefaultForMismatchedProperty) { // o = m.Setter(o, m.IsValueType ? System.Runtime.Serialization.FormatterServices.GetUninitializedObject(m.MemberType) : null); // Console.WriteLine("Error when setting " + m.MemberName); // continue; // } // throw; //} } } if (si != null) { si.OnDeserialized(o); } return(o); }