JSON.NET在没有try / catch的情况下解析可选值

时间:2014-03-10 21:48:24

标签: c# json linq json.net

因此,我一直在为之工作的公司要求我为需要使用.NET访问我们的API的客户公司制作一个C#库。到目前为止,我有一个工作库,但我一直在解析可选属性时遇到问题。我们在后端使用mongoDB,而mongoDB不存储未提供的属性,即使它们已在模式中定义。

例如,我的架构可能如下所示:

{
   name:String,
   id:Number,
   phone:String,
   email:String,
   experience:[]
}

我在哪里制作文件:

{
   name:"joe",
   id:5,
   phone:"222-222-2222",
}

我的文档中不存在属性emailexperience,因此我的JSON看起来与上面显示的完全相同。但是,这些值不是必需值,但我仍然需要解析其余的值。问题是,当我在解析emailexperience时解析上面的代码以获取所有可能的值时,解析器会抛出一个Null Reference Exception,并且有充分的理由因为我正在尝试的值解析不存在,我引用这些值的方式如下:

JObject o=JObject.Parse(json); //parse json to JObject json object
string name=(string)o["name"];
int id=(int)o["id"];
string phone=(string)o["phone"];
string email=(string)o["emain"];
List<string> exp=o["experience"].Select(t => (string)t).ToList();

现在我的代码更客观了,我使用LINQ创建一个名为Job的对象和一个对象Jobs来存储JObject,以便您可以使用它来查询某些值使用原始JSON字符串初始化的Jobs对象的方法。

我认为处理JSON中的可选属性的唯一方法是尝试/捕获每个值。这似乎非常草率,我必须解析的JSON总共约40-50个属性。这似乎是非常缓慢和代码的混乱。我想知道我是否可以实现这是一种更清洁更有效的方式。

1 个答案:

答案 0 :(得分:6)

除非有充分的理由不能使用通用的反序列化/序列化方法,否则我建议您改变使用方法。一般来说,我认为你在上面做的有条件的,属性特定的解析类型是非常糟糕的做法。这是一个例子;

public class Job
{
   public string name;
   public string id;
   public string phone;
   public string email;
   public string[] experience; // can also be a List<string> without any problems
}

Job j = JsonConvert.DeserializeObject<Job>(jsonString);

string output = JsonConvert.SerializeObject(j);
//will include "optional" parameters, meaning if there is no phone value it will be an empty string but the property name will still be there.

如果你真的想确认这一点,那么包含一些必需的参数但是其他一些可选的参数不是我建议将json模式与json.NET结合使用。您可以执行以下操作;

//schema in flat text file I read with File.ReadAllText(path);
{
    "type":"object",
    "$schema": "http://json-schema.org/draft-03/schema",
    "required":true,
    "properties":{
        "name": { "type":"string", "required":true },
        "id": { "type":"string", "required":true },
                "phone": { "type":"string", "required":false },
                "email": { "type":"string", "required":false },
                "experience": { "type":"array", "required":true, "items": { "string" } }
    }
}

然后在代码中你有类似的东西;

JObject obj = JObject.Parse(json);
JsonSchema jscheme = JsonSchema.Parse(File.ReadAllText(thatSchemaAbove));
IList<string> errors;
obj.IsValid(jscheme, out errors);
if (errors.Count() > 0)
{
     //json didn't match the schema, do something about it!
}

编辑:处理复杂的对象;

假设您的json是一个对象,其中包含一组名为Job的{​​{1}}个对象。使用以下C#类定义;

jobs

json中使用的任何构造都具有C#等价物,你只需要分解它并确定它是什么。