/// <summary> /// Writes the JSON representation of the object. /// </summary> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="value">The value.</param> /// <param name="serializer">The calling serializer.</param> public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; Type t = value.GetType(); object result = FSharpUtils.GetUnionFields(null, value, t, null); object info = FSharpUtils.GetUnionCaseInfo(result); object fields = FSharpUtils.GetUnionCaseFields(result); object caseName = FSharpUtils.GetUnionCaseInfoName(info); object[] fieldsAsArray = fields as object[]; writer.WriteStartObject(); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(CasePropertyName) : CasePropertyName); writer.WriteValue((string)caseName); if (fieldsAsArray != null && fieldsAsArray.Length > 0) { writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName); serializer.Serialize(writer, fields); } writer.WriteEndObject(); }
private static Union CreateUnion(Type t) { Union u = new Union(); u.TagReader = (FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, t, null); u.Cases = new List <UnionCase>(); object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null); foreach (object unionCaseInfo in cases) { UnionCase unionCase = new UnionCase(); unionCase.Tag = (int)FSharpUtils.GetUnionCaseInfoTag(unionCaseInfo); unionCase.Name = (string)FSharpUtils.GetUnionCaseInfoName(unionCaseInfo); unionCase.Fields = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(unionCaseInfo); unionCase.FieldReader = (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, unionCaseInfo, null); unionCase.Constructor = (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, unionCaseInfo, null); u.Cases.Add(unionCase); } return(u); }
private static DiscriminatedUnionConverter.Union CreateUnion(Type t) { DiscriminatedUnionConverter.Union union = new DiscriminatedUnionConverter.Union() { TagReader = (FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, new object[] { t, null }), Cases = new List <DiscriminatedUnionConverter.UnionCase>() }; object[] getUnionCases = (object[])FSharpUtils.GetUnionCases(null, new object[] { t, null }); for (int i = 0; i < (int)getUnionCases.Length; i++) { object obj = getUnionCases[i]; DiscriminatedUnionConverter.UnionCase unionCase = new DiscriminatedUnionConverter.UnionCase() { Tag = (int)FSharpUtils.GetUnionCaseInfoTag(obj), Name = (string)FSharpUtils.GetUnionCaseInfoName(obj), Fields = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(obj, new object[0]), FieldReader = (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, new object[] { obj, null }), Constructor = (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, new object[] { obj, null }) }; union.Cases.Add(unionCase); } return(union); }
/// <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)); }