I am deserializing JSON strings into using Person objects using this code:

JavaScriptSerializer serializer = new JavaScriptSerializer();
Person person = serializer.Deserialize<Person>(jsonString);

The Person class has an Age property:

int Age {get;set;}

The JSON string has a value like:

{age: 'not valid int'}

and I am getting an exception as follows:

Cannot cast string to Int32

Is there any way to tell the JavaScriptSerializer to skip on error and continue with the other properties?

有帮助吗?

解决方案

Yes, it is possible to control the deserialization process by writing a custom JavaScriptConverter class:

public class PersonConverter : JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        Person person = new Person();

        foreach (string key in dictionary.Keys)
        {
            var value = dictionary[key];

            switch (key)
            {
                case "Name":
                    person.Name = (string)value;
                    break;

                case "Age":
                    {
                        if (value is int)
                        {
                            person.Age = (int)value;
                        }
                        else
                        {
                            int age;
                            if (int.TryParse((string)dictionary[key], out age))
                            {
                                person.Age = age;
                            } // else leave Age as null (or if int, leave as 0); alternatively put an else block here to set to value of your choice
                        }
                    }
                    break;
            }
        }

        return person;
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get
        {
            return new[] { typeof(Person) };
        }
    }
}

I have taken the liberty of making Person.Age nullable, where null indicates that the age is unknown, but if this is not acceptable you could modify the converter to default to 0 or -1 when the age was not parseable:

public class Person
{
    public string Name { get; set; }
    public int? Age { get; set; }
}

Usage:

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new PersonConverter() });
var person = serializer.Deserialize<Person>(jsonString);

Example with output:

    var serializer = new JavaScriptSerializer();
    serializer.RegisterConverters(new[] { new PersonConverter() });

    var jsonStrings = new List<string>
    {
        "{ Name: 'Steve',  Age: 21 }",
        "{ Name: 'Teoman',  Age: 'not valid int'}",
        "{ Name: 'Queen Elizabeth II',  Age: '89'}"
    };

    foreach (var jsonString in jsonStrings)
    {
        var person = serializer.Deserialize<Person>(jsonString);
        Console.WriteLine("Name: {0}, Age: {1}", person.Name, person.Age);
    }

Name: Steve, Age: 21

Name: Teoman, Age:

Name: Queen Elizabeth II, Age: 89

Please note that we have handled here: a literal number, a number inside a string, and a totally invalid value.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top