Esempio n. 1
0
        /// <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));
        }
Esempio n. 2
0
        /// <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));
        }