/// <summary> /// Reads the JSON representation of the object. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> to read from.</param> /// <param name="objectType">Type of the object.</param> /// <param name="existingValue">The existing value of object being read.</param> /// <param name="serializer">The calling serializer.</param> /// <returns>The object value.</returns> public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return(null); } IEnumerable cases = (IEnumerable)FSharpUtils.GetUnionCases(null, objectType, null); ReadAndAssertProperty(reader, CasePropertyName); ReadAndAssert(reader); string caseName = reader.Value.ToString(); object matchingCaseInfo = null; foreach (object c in cases) { if ((string)FSharpUtils.GetUnionCaseInfoName(c) == caseName) { matchingCaseInfo = c; break; } } if (matchingCaseInfo == null) { throw new JsonSerializationException("No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); } ReadAndAssertProperty(reader, FieldsPropertyName); // start array ReadAndAssert(reader); // first value ReadAndAssert(reader); PropertyInfo[] fieldProperties = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(matchingCaseInfo); List <object> fieldValues = new List <object>(); foreach (PropertyInfo field in fieldProperties) { fieldValues.Add(serializer.Deserialize(reader, field.PropertyType)); ReadAndAssert(reader); } // end object ReadAndAssert(reader); return(FSharpUtils.MakeUnion(null, matchingCaseInfo, fieldValues.ToArray(), null)); }
/// <summary> /// Reads the JSON representation of the object. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> to read from.</param> /// <param name="objectType">Type of the object.</param> /// <param name="existingValue">The existing value of object being read.</param> /// <param name="serializer">The calling serializer.</param> /// <returns>The object value.</returns> public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return(null); } object matchingCaseInfo = null; string caseName = null; JArray fields = null; // start object ReadAndAssert(reader); while (reader.TokenType == JsonToken.PropertyName) { string propertyName = reader.Value.ToString(); if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase)) { ReadAndAssert(reader); IEnumerable cases = (IEnumerable)FSharpUtils.GetUnionCases(null, objectType, null); caseName = reader.Value.ToString(); foreach (object c in cases) { if ((string)FSharpUtils.GetUnionCaseInfoName(c) == caseName) { matchingCaseInfo = c; break; } } if (matchingCaseInfo == null) { throw JsonSerializationException.Create(reader, "No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); } } else if (string.Equals(propertyName, FieldsPropertyName, StringComparison.OrdinalIgnoreCase)) { ReadAndAssert(reader); if (reader.TokenType != JsonToken.StartArray) { throw JsonSerializationException.Create(reader, "Union fields must been an array."); } fields = (JArray)JToken.ReadFrom(reader); } else { throw JsonSerializationException.Create(reader, "Unexpected property '{0}' found when reading union.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } ReadAndAssert(reader); } if (matchingCaseInfo == null) { throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName)); } if (fields == null) { throw JsonSerializationException.Create(reader, "No '{0}' property with union fields found.".FormatWith(CultureInfo.InvariantCulture, FieldsPropertyName)); } PropertyInfo[] fieldProperties = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(matchingCaseInfo); if (fieldProperties.Length != fields.Count) { throw JsonSerializationException.Create(reader, "The number of field values does not match the number of properties definied by union '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); } object[] typedFieldValues = new object[fieldProperties.Length]; for (int i = 0; i < fields.Count; i++) { JToken t = fields[i]; PropertyInfo fieldProperty = fieldProperties[i]; typedFieldValues[i] = t.ToObject(fieldProperty.PropertyType); } return(FSharpUtils.MakeUnion(null, matchingCaseInfo, typedFieldValues, null)); }