如何根据反序列化json字符串的响应在两个类之间切换?

Posted

技术标签:

【中文标题】如何根据反序列化json字符串的响应在两个类之间切换?【英文标题】:How to switch between two classes as per response for deserialize json string? 【发布时间】:2018-02-09 09:04:45 【问题描述】:

我正在研究 xamarin.forms。我在 API 调用期间遇到问题。 我有一个用于登录的 API。

当电子邮件和密码有效时,回复为


    "status": true,
    "statusCode": 200,
    "response": 
        "Id": "83ae239e-764e-4cef-af86-363664a3a65a",
        "Email": "rutul.mehta@atozinfoway.com",
        "EmailConfirmed": false,
        "PasswordHash": "AFetO7VdrveGEfVZEezldzkOkh6Xs0/JR18+0QDptO56UJzY5qgwpZcpudNM2cVxFA==",
        "SecurityStamp": "f062b486-f19a-4981-96a7-0fc72f17e99f",
        "PhoneNumber": null,
        "PhoneNumberConfirmed": false,
        "TwoFactorEnabled": false,
        "LockoutEndDateUtc": null,
        "LockoutEnabled": true,
        "AccessFailedCount": 0,
        "UserName": "rutul.mehta@atozinfoway.com",
        "UserId": 5,
        "Name": "Rutul",
        "ZipCode": null,
        "CountryId": null,
        "IsDeleted": false,
        "CreatedDate": "2017-08-23T13:41:22"
    

Json 转 C# 类是:

public class Response
        
            public string Id  get; set; 
            public string Email  get; set; 
            public bool EmailConfirmed  get; set; 
            public string PasswordHash  get; set; 
            public string SecurityStamp  get; set; 
            public object PhoneNumber  get; set; 
            public bool PhoneNumberConfirmed  get; set; 
            public bool TwoFactorEnabled  get; set; 
            public object LockoutEndDateUtc  get; set; 
            public bool LockoutEnabled  get; set; 
            public int AccessFailedCount  get; set; 
            public string UserName  get; set; 
            public int UserId  get; set; 
            public string Name  get; set; 
            public object ZipCode  get; set; 
            public object CountryId  get; set; 
            public bool IsDeleted  get; set; 
            public string CreatedDate  get; set; 
        

        public class RootObject
        
            public bool status  get; set; 
            public int statusCode  get; set; 
            public Response response  get; set; 
        

返回类型为“Response”的属性下方的“RootObject”类

公共响应响应 获取;放;

如果电子邮件和密码无效,则响应为:


    "status": false,
    "statusCode": 203,
    "response": "Invalid Email or Password."

json 到 c# 类是:

public class RootObject

    public bool status  get; set; 
    public int statusCode  get; set; 
    public string response  get; set; 

在具有返回类型字符串的属性下面的“RootObject”类中

公共字符串响应 获取;放;

我在反序列化对象时遇到问题

服务调用函数:

private async Task GetService_SignIn()
        
            try
            
                string url = ServiceURLs.SignIn + "email=" + txtEmail.Text + "&password=" + txtPassword.Text;
                var Service_response = await GetResponseFromWebService.GetResponse<SignIn.RootObject>(url);
                if (Service_response != null)
                
                    if (Service_response.status)
                    
                        // Application.Current.MainPage = new SideMenu();
                        Alert("Success", "Login success", "icon.png", Color.Green);
                    
                    else
                    
                        if (Service_response.statusCode == 417)
                        
                            Alert("Alert", "WebServer Exception", "icon.png", Color.Red);
                        
                        else if (Service_response.statusCode == 203)
                        
                            Alert("Alert", "Invalid Email or Password", "icon.png", Color.Red);
                        
                    
                
                else
                
                    Alert("Alert", "WebServer not Responding", "icon.png", Color.Red);
                
            
            catch (WebException ex)
            
                Alert("Exception", ex.Message, "icon.png", Color.Red);
            
         

获取响应的通用类:

public static async Task<T> GetResponse<T>(string URI) where T : class
        
            if (NetworkInterface.GetIsNetworkAvailable())
            
                HttpClient httpClient = new HttpClient();
                //httpClient.DefaultRequestHeaders.IfModifiedSince = DateTimeOffset.Now;
                //httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Token", "dc642a7f5bd64912");

                var request = new HttpRequestMessage(HttpMethod.Get, URI);

                if (request.Headers.CacheControl == null)
                
                    request.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue();
                

                request.Headers.CacheControl.NoCache = true;

                var response1 = await httpClient.SendAsync(request);
                if (response1 != null && response1.IsSuccessStatusCode)
                
                    var responseString = await response1.Content.ReadAsStringAsync();

                    if (!string.IsNullOrWhiteSpace(responseString))
                    
                        return JsonConvert.DeserializeObject<T>(responseString);
                    
                
            
            return null;
        

当电子邮件和密码无效时,我从下面一行收到异常

return JsonConvert.DeserializeObject(responseString);

如何根据响应在两个类之间切换?如果我没有反序列化 json 响应如何知道状态码?

如何在 c# 中处理这种设置?

【问题讨论】:

返回 Response 类并带有“失败”信息。 是的,必须更改此 Web 服务。我只是在消费服务。有可能从我们这边处理吗? 【参考方案1】:

假设您正在使用 Newtonsoft - 您可以在 RootObjectResponse 属性中添加 JsonConverter 属性。转换器可以检测响应是否为字符串(在运行时)并将其分配给Response 实例上的某个属性。

更多细节here关于如何创建一个和here关于如何使用属性分配给属性。

一个示例 json-converter 如下所示:

public class StringToResponseConverter : JsonConverter

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    
        throw new NotImplementedException();
    

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        object retVal = new Object();
        if (reader.TokenType == JsonToken.StartObject)
        
            var instance = (Response)serializer.Deserialize(reader, typeof(Response));
            retVal = instance;
        
        else if (reader.TokenType == JsonToken.String)
        
            string message = (string)serializer.Deserialize(reader);
            retVal = new Response  Message = message ;
        

        return retVal;
    

    public override bool CanConvert(Type objectType)
    
        return true;
    

还有,用法:

public class RootObject

    public bool status  get; set; 
    public int statusCode  get; set; 
    [JsonConverter(typeof(StringToResponseConverter))]
    public Response response  get; set; 

【讨论】:

是的,我正在使用 Newtonsoft。我正在尝试您的建议。 @rutul-mehta :添加了一些代码示例 - 希望对您有所帮助! 非常感谢,一切正常。另一种方法是使返回类型 .

以上是关于如何根据反序列化json字符串的响应在两个类之间切换?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JSON-B 将 JSON 字符串反序列化为非公共类?

Groovyjson 字符串反序列化 ( 使用 JsonSlurper 进行 json 字符串反序列化 | 根据 map 集合构造相关类 )

如何使用 Gson @SerializedName 注释在 Kotlin 中反序列化嵌套的 Json API 响应

如何反序列化 JSONP 响应(最好使用 JsonTextReader 而不是字符串)?

如何反序列化 JSONP 响应(最好使用 JsonTextReader 而不是字符串)?

将Json字符串反序列化为对象java