所以我一直工作的公司要求我为客户公司做一个c#库,他们需要用。net访问我们的API。到目前为止,我有一个工作库,但我一直在解析可选属性时遇到问题。我们在后端使用mongoDB,并且mongoDB不会存储未提供的属性,即使它们在模式中定义。
例如,我的模式可能看起来像:
{
name:String,
id:Number,
phone:String,
email:String,
experience:[]
}
创建文档的位置:
{
name:"joe",
id:5,
phone:"222-222-2222",
}
属性email
和experience
在我的文档中不存在,所以我的JSON看起来与上面显示的完全一样。然而,这些值不是必需的值,但我仍然需要解析它的其余部分。问题是,当我为所有可能的值解析上面的代码时,当我解析email
或experience
时,解析器抛出一个空引用异常,并且有很好的理由,因为我试图解析的值不存在,我引用这些值的方式是这样的:
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,在这种方式下,您可以使用Jobs
对象的方法来查询它的某些值,该方法初始化了原始JSON字符串。
事情是我能想到的处理JSON中的可选属性的唯一方法是尝试/捕获每个值。这看起来很草率,我需要解析的JSON总共有40-50个属性。这看起来会非常慢,而且代码会非常混乱。我想知道我是否可以实现这是一个更干净,更有效的方式。
除非有很好的理由不能使用通用的反序列化/序列化方法,否则我建议您更改方法以使用这些方法。一般来说,我认为您上面所做的条件、属性特定解析类型是非常糟糕的实践。下面是一个例子;
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
对象数组的对象,称为jobs
。使用下面的c#类定义;
public class jobsWrapper
{
public List<Job> jobs;
}
json中使用的任何结构都有c#的等效结构,你只需要分解它并确定它是什么