RestSharp如何处理同一查询的不同JSON响应格式

时间:2017-08-02 06:56:35

标签: c# json wpf rest restsharp

我一直在与此斗争一段时间,我认为是时候寻求帮助了。

我正在使用 RestSharp 连接到我的本地 PHP REST API 。我正在返回api结果的格式如下(JSON):

{
"estado": "login_correcto",
"content": {
   "id": 1,
   "nombreusuario": "daniaguado",
   "contrasena": "qwerty",
   "email": "daniel@zadecon.com",
   "nivelacceso": 5,
    "created_at": "2017-08-01 10:31:16",
    "updated_at": "-0001-11-30 00:00:00"
    }
}

为此,我创建了一个自定义Usuario类(用户)和一个自定义ResponseUsuario,如下所示:

class Usuario
{
    public int id { get; set; }
    public string nombreusuario { get; set; }
    public string contrasena { get; set; }
    public string email { get; set; }
    public int nivelacceso { get; set; }
    public string created_at { get; set; }
    public string updated_at { get; set; }
}

然后是ResponseUsuario:

class ResponseUsuario
{
    public string estado { get; set; }
    public Usuario content { get; set; }
}

当响应正常(202)且用户存在时,正在解析响应。

但是,当登录不正确时,在“内容”中我将返回一条消息,而不是用户:

{
 "estado": "login_incorrecto",
 "content": "La contraseña es incorrecta / Password incorrect"
}

因此,如果我在那里使用ResponseUsuario,则queryResult.Data为null,因为它无法将内容映射到Usuario类。事实是,如果我不使用ResponseUsuario而是使用Response类,其中内容变量是类型对象,我无法将其强制转换为Usuario而我无法处理它。

这是我更了解的Response类,我应该用它来解决所有问题:

class Response
{
    public string estado { get; set; }
    public object content { get; set; }
}

最后,这是我的RestSharp查询:

ApiClient api = new ApiClient(); // Just create the client with some common parameters

var request = new RestRequest("usuarios/login", RestSharp.Method.POST);

request.AddParameter("nombreusuario", textbox_usuario.Text);
request.AddParameter("contrasena", textbox_contrasena.Text);

var queryResult = api.cliente.Execute<ResponseUsuario>(request);

if (queryResult.StatusCode == System.Net.HttpStatusCode.OK)
{
    Usuario u = (Usuario) queryResult.Data.content; // Gives error when using Execute<Response> (object content)
    String s = queryResult.Data.estado;

    Console.Out.WriteLineAsync($"OK - {u.nombreusuario} - {u.email} - Acceso: {u.nivelacceso}");
} 
else
{
    Console.Out.WriteLineAsync($"Query Failed: {queryResult.StatusDescription}, estado: {queryResult.Data.estado}"); // Giving error when using Execute<ResponseUsuario>
}

如何将演员表修复为Usuario(或匹配的内容类)?我认为Response类对于我对API的所有查询都应该是通用的,然后将内容部分转换为它的适当类,但我不知道该怎么做。

4 个答案:

答案 0 :(得分:1)

参加聚会真的很晚。当一个API返回错误而不是200的不同结构时,我遇到了类似的问题。我放弃了RestSharp的类型化调用,并明确反序列化了有效负载。

var response = RestClient.Execute<IdamValidationResultApiModel>(request);
if (response.IsSuccessful)
   var t1 = JsonConvert.DeserializeObject<FirstType>(response.Content);
else
   var t2 = JsonConvert.DeserializeObject<SecondType>(response.Content);

答案 1 :(得分:0)

检查if(queryResult.Data.content是否为Usuario)并仅在其为真时进行强制转换

否则转换为字符串。

答案 2 :(得分:0)

每个响应都返回不同的Http状态代码吗?我猜你从你的休息api那里回来了401。如果是这种情况:

然后,您可以使用开关处理其他状态代码。

    HttpStatusCode statusCode = queryResult.StatusCode;
    int numericStatusCode = (int)statusCode;

    switch (numericStatusCode)
    {
        case 202:
            dynamic content = queryResult.Data.content;
            Usuario u = content.content; 
            String s = queryResult.Data.estado;
            Console.Out.WriteLineAsync($"OK - {u.nombreusuario} - {u.email} - Acceso: {u.nivelacceso}");
            break;
        case 401:
            //Deal with the failed login
            break;
    }

最后,您收到错误的原因是因为您正在尝试将UsarioResponse类型的响应对象强制转换为Usario。您需要导航json以查找content.content(如上所示)

答案 3 :(得分:0)

我终于通过从Dictionary对象生成一个自定义反射到类,即最后一个自定义解析器来解决这个问题。

我创建了一个新类Tools并添加了一个转换函数:

public static T CastToObject<T>(IDictionary<string, object> dict) where T : class
{
   Type type = typeof(T);
   T result = (T)Activator.CreateInstance(type);
   foreach (var item in dict)
   {
       type.GetProperty(item.Key).SetValue(result, item.Value, null);
   }
   return result;
 }

在Api查询中,根据状态代码添加了一个switch-case:

var queryResult = api.cliente.Execute<Response>(request);

switch(queryResult.StatusCode)
{
    case System.Net.HttpStatusCode.OK:
        Usuario u = Tools.CastToObject<Usuario>((IDictionary<string, object>)queryResult.Data.content);
        String status = queryResult.Data.estado;
        Console.Out.WriteLineAsync($"OK - {u.nombreusuario} - {u.email} - Acceso: {u.nivelacceso}");
        break;
    case System.Net.HttpStatusCode.NotFound:
            Console.Out.WriteLineAsync($"Login Failed: User does not exists");
            break;
    case System.Net.HttpStatusCode.Unauthorized:
            Console.Out.WriteLineAsync($"Login Failed: Incorrect Password");
            break;
    default:
            Console.Out.WriteLineAsync($"Error when connecting to the API");
            break;
}

此外,我需要处理包含content字段内的列表的响应,但我认为该过程与此类似:为content字段创建自定义解析器把它投到我的班上。