void EncodeObject(object value, bool forceTypeHint) { var type = value.GetType(); WriteStartObject(); // if this returns true, we have a reference so we are done if (WriteOptionalReferenceData(value)) { WriteEndObject(); return; } WriteOptionalTypeHint(type, forceTypeHint); // check for an override converter and use it if present var converter = _settings.GetTypeConverterForType(type); if (converter != null && converter.CanWrite) { converter.WriteJson(this, value); if (converter.WantsExclusiveWrite) { WriteEndObject(); return; } } foreach (var field in _cacheResolver.GetEncodableFieldsForType(type)) { WriteValueDelimiter(); EncodeString(field.Name); AppendColon(); EncodeValue(field.GetValue(value)); } foreach (var property in _cacheResolver.GetEncodablePropertiesForType(type)) { if (property.CanRead) { WriteValueDelimiter(); EncodeString(property.Name); AppendColon(); try { EncodeValue(property.GetValue(value, null)); } catch (Exception e) { // encode failed. stick a default value in there EncodeValue(type.IsValueType ? Activator.CreateInstance(type) : null); System.Console.WriteLine($"Failed to write property {property.Name} for type {type.Name}. {e}"); } } } WriteEndObject(); }
/// <summary> /// grabs the Field/PropertyInfo of <paramref name="obj"/> for <paramref name="key"/> and sets it /// with the next element in the JSON string. /// </summary> /// <param name="obj">Object.</param> /// <param name="key">Key.</param> void SetNextValueOnObject(ref object obj, string key) { var field = _cacheResolver.GetField(obj.GetType(), key); if (field != null) { if (_cacheResolver.IsMemberInfoEncodeableOrDecodeable(field, field.IsPublic)) { var value = DecodeValue(GetNextToken(), field.FieldType); if (obj.GetType().IsValueType) { // obj is a struct. var instanceRef = obj; field.SetValue(instanceRef, value); obj = instanceRef; return; } // obj is a class. field.SetValue(obj, value); return; } } var property = _cacheResolver.GetProperty(obj.GetType(), key); if (property != null) { if (property != null && property.CanWrite && property.IsDefined(JsonConstants.includeAttrType)) { var value = DecodeValue(GetNextToken(), property.PropertyType); if (obj.GetType().IsValueType) { // obj is a struct. var instanceRef = obj; property.SetValue(instanceRef, value); obj = instanceRef; return; } // obj is a class. property.SetValue(obj, value); return; } } // we still need to eat the value even if we didnt set it so the parser is in the right spot var orhpanedValue = DecodeValueUntyped(GetNextToken()); // check for a JsonConverter and use it if we have one var converter = _settings?.GetTypeConverterForType(obj.GetType()); if (converter != null && converter.CanRead) { converter.OnFoundCustomData(obj, key, orhpanedValue); } }