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

tst*_*rzl 0 c# linq json json.net

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

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

{
   name:String,
   id:Number,
   phone:String,
   email:String,
   experience:[]
}
Run Code Online (Sandbox Code Playgroud)

我在哪里制作文件:

{
   name:"joe",
   id:5,
   phone:"222-222-2222",
}
Run Code Online (Sandbox Code Playgroud)

性能emailexperience不要在我的文档存在,所以我的JSON看起来完全如上面显示.但是,这些值不是必需值,但我仍然需要解析其余的值.问题是当我解析上面的代码时我解析所有可能的值emailexperience解析器抛出一个Null引用异常,并且有充分的理由因为我试图解析的值不存在以及我引用它们的方式值是这样的:

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();
Run Code Online (Sandbox Code Playgroud)

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

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

eva*_*nal 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.
Run Code Online (Sandbox Code Playgroud)

如果你真的想确认这一点,那么包含一些必需的参数,但是其他一些可选参数不是我建议将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" } }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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!
}
Run Code Online (Sandbox Code Playgroud)

编辑:处理复杂的对象;

假装你的json是一个带有Job被调用对象数组的对象jobs.使用以下C#类定义;

public class jobsWrapper
{
    public List<Job> jobs;
}
Run Code Online (Sandbox Code Playgroud)

在json中使用的任何构造都具有C#等价物,您只需要对其进行分解并确定它是什么.