JSON 字符串验证超过一个 class

JSON string validate with more than one class

在我的业务流程中,我可能有 JSON 个不同格式的字符串。

例如:

String jsonSring = readValue();//this JSON String may contain Teacher object or Student Object

目前我正在使用这个简单的方法来验证 JSON 是否相对于 TeacherStudent:

try{
    Teacher teacher = om.readValue(jsonSring, Teacher.class);
}catch(Exception e){
    Student student = om.readValue(jsonSring, Student.class);
}

有任何验证 JSON 内容的简化方法吗?

解决方案 1:添加一个 Type 字段:

添加指定对象类型的字段可能是最简单的选择,但您必须能够更改对象才能做到这一点。

public Enum UserType { Teacher, Student, /* possibly other types */ }

public interface ISchoolMember 
{
    public string Name { get; }
    ..
    public UserType Type { get; }
}

然后一旦有了 JSON,就可以将其解析为 JObject 并读取 Type 字段:

public ISchoolMember Deserialize(string jsonString)
{ 
    var o = JObject.Parse(jsonString);
    return (UserType)o["Type"] switch
    {
        UserType.Teacher => JsonConvert.Deserialize<Teacher>(jsonString),
        UserType.Student => JsonConvert.Deserialize<Student>(jsonString),
        _ => throw new ArgumentException("...")
    };
}

解决方案 2:检查特殊字段。

如果无法添加新字段,您可以检查解析后的 JObject 是否包含仅属于两个对象之一的字段:

public void DeserializeAndDoStuff(string jsonString)
{ 
    var teacherOrStudent = JObject.Parse(jsonString);
    if (teacherOrStudent["StudentId"] != null) // it is a student!
    {
        Student s = teacherOrStudent.ToObject<Student>();
        // ... do stuff with the student object
    } 
    else if (teacherOrStudent["TeacherId"] != null) // it is a teacher!
    {
        Teacher t = teacherOrStudent.ToObject<Teacher>();
        // ... do stuff with the teacher object
    }
    else 
    {
        throw new ArgumentException("The given object is neither a teacher or a student.");
    }
}

这两种方法看起来比原来的方法更冗长,但有助于摆脱基于异常的编程(总是不建议这样做,因为处理异常在资源方面非常昂贵)。

p.s.
此实现使用 Newtonsoft.Json 库,但我猜其他库也有类似的机制。