Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
i get following 2 reponse from 1 API Call

1) {
    "id": 200,
    "msg": "Successful",
    "trans_id": "415",
    "info": {
        "id": "41",
        "number": "3889 is already exists"
    }
}


2)
{
     "id": 400,
    "msg": "Bad Request",
    "trans_id": "CLIENTAPI202306050146459",
    "info": [
        "state : value must be a valid string",
        "city : value must be a valid string"
    ]
}


Following is my class file

public class Output
    {
        public string id { get; set; }
        public string msg { get; set; }
        public string trans_id { get; set; }
        public List<string> info { get; set; }
    }


How can i handle above 2 responses from using 1 class file,

i am using following to send response

{
                    var responseData = httpresponsemessage.Content.ReadAsStringAsync().Result;
                    strinputjson = responseData.ToString();
                    ErrorHandler.LogSteps(strinputjson, "JsonOutput");
                    //var stuff = JsonConvert.DeserializeObject<List<RootObject>>(strinputjson).ToString();
                    tResponse = JsonConvert.DeserializeObject<TResponse>(strinputjson);
                    

                } 


or There is another way to handled this response??
beacuse i try to run above code it give me following error

Error: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[System.String]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<t>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'info.case_id', line 6, position 18

What I have tried:

I tried many thing but it give me invalid json conversion error
Posted
Updated 13-Jun-23 18:27pm
v2
Comments
Akshay malvankar 13-Jun-23 7:39am    
Can we do that using 1 single class file??
Richard Deeming 14-Jun-23 3:18am    
Of course, the simplest solution is to get the people who write the API to fix their code to produce consistent JSON - either always return a list of objects, or use a different property name for the list of strings.

Quite how easy it will be to get them to accept and fix the problem is a different matter... :)

It is unusual to see a success and error result returned using the same property name in a JSON result. This does not mean that it can not be handled.

You have tagged your question with ASP.NET5, so I am going to focus on a .Net 5.0+ solution, so I will be using System.Text.Json for deserialization. I will do this using a Console app.

As the info property can be 2 different types, we need to enable support. To do this, I am going to use JsonElement to hold the info property data, then deserialize based on the result code - 200 = success, 400 = bad request.
C#
public class Output
{
    public int id { get; set; }
    
    public string msg { get; set; }
    
    public string trans_id { get; set; }
    
    public JsonElement info { get; set; }
}

Next we need a class to hold the Success and Error results.
C#
public class Info
{
    public Data? Data { get; set; }
    public List<String>? Errors { get; set; }
}

And we need a class to hold the success data:
C#
public class Data
{
    public string id { get; set; }
    public string number { get; set; }
}

Now we are ready to process and deserialize.
C#
Info? JsonToInfo(string rawJson)
{
    Output? result = JsonSerializer.Deserialize<Output>(rawJson);

    return result?.id switch
    {
        200 => new Info
        {
            Data = result.info.Deserialize<Data>(jsonSerializerOptions)
        },
        400 => new Info
        {
            Errors = result.info.Deserialize<List<string>>(jsonSerializerOptions)
        },
        _ => null
    };
}

Here we deserialize the returned json, and then deserialize the info property and return that dependant on the return code in the root id property.

Here is the complete test project:
C#
using System.Text.Json;

string rawJsonSuccess = 
    """"
    {
        "id": 200,
        "msg": "Successful",
        "trans_id": "415",
        "info": {
            "id": "41",
            "number": "3889 is already exists"
        }
    }
    """";

string rawJsonBadRequest = 
    """"
    {
         "id": 400,
        "msg": "Bad Request",
        "trans_id": "CLIENTAPI202306050146459",
        "info": [
            "state : value must be a valid string",
            "city : value must be a valid string"
        ]
    }
    """";

JsonSerializerOptions? jsonSerializerOptions = new();

Info? successResult = JsonToInfo(rawJsonSuccess);
DumpSuccess(successResult);
Console.WriteLine("----------");
Console.WriteLine();
void DumpSuccess(Info? info)
{
    if (info is null)
    {
        Console.WriteLine("No Info data");
        return;
    }

    Console.WriteLine($"ID:     {info.Data!.id}");
    Console.WriteLine($"NUMBER: {info.Data!.number}");
}

Info? badRequestResult = JsonToInfo(rawJsonBadRequest);
DumpBadRequest(badRequestResult);

void DumpBadRequest(Info? info)
{
    if (info is null)
    {
        Console.WriteLine("No Error data");
        return;
    }

    Console.WriteLine("Errors returned:");
    foreach (string error in info.Errors!)
    {
        Console.WriteLine($" > {error}");
    }
}


Info? JsonToInfo(string rawJson)
{
    Output? result = JsonSerializer.Deserialize<Output>(rawJson);

    return result?.id switch
    {
        200 => new Info
        {
            Data = result.info.Deserialize<Data>(jsonSerializerOptions)
        },
        400 => new Info
        {
            Errors = result.info.Deserialize<List<string>>(jsonSerializerOptions)
        },
        _ => null
    };
}

public class Output
{
    public int id { get; set; }
    
    public string? msg { get; set; }
    
    public string? trans_id { get; set; }
    
    public JsonElement info { get; set; }
}

public class Info
{
    public Data? Data { get; set; }
    public List<string>? Errors { get; set; }
}

public class Data
{
    public string? id { get; set; }
    public string? number { get; set; }
}

and the output:
ID:     41
NUMBER: 3889 is already exists
----------

Errors returned:
 > state : value must be a valid string
 > city : value must be a valid string


UPDATE

If you want the header/root data, you can move the Info class into the Output class:
C#
public class Output
{
    public int id { get; set; }
    
    public string? msg { get; set; }
    
    public string? trans_id { get; set; }
    
    public JsonElement info { get; set; }

    [JsonIgnore]
    public Info? InfoData { get; set; }
}

Then deserialization would be:
C#
Output? DeserializeJson(string rawJson)
{
    Output? result = JsonSerializer.Deserialize<Output>(rawJson);

    if (result is null)
        return null;

    result.InfoData = result?.id switch
    {
        200 => new Info
        {
            Data = result.info.Deserialize<Data>(jsonSerializerOptions)
        },
        400 => new Info
        {
            Errors = result.info.Deserialize<List<string>>(jsonSerializerOptions)
        },
        _ => null
    };

    return result;
}

Here is the full project:
C#
using System.Text.Json;
using System.Text.Json.Serialization;

string rawJsonSuccess = 
    """"
    {
        "id": 200,
        "msg": "Successful",
        "trans_id": "415",
        "info": {
            "id": "41",
            "number": "3889 is already exists"
        }
    }
    """";

string rawJsonBadRequest = 
    """"
    {
         "id": 400,
        "msg": "Bad Request",
        "trans_id": "CLIENTAPI202306050146459",
        "info": [
            "state : value must be a valid string",
            "city : value must be a valid string"
        ]
    }
    """";

JsonSerializerOptions? jsonSerializerOptions = new();

Output? successResult = DeserializeJson(rawJsonSuccess);
DumpState(successResult);
DumpSuccess(successResult);
Console.WriteLine("----------");
Console.WriteLine();

void DumpSuccess(Output? output)
{
    if (output is null)
    {
        Console.WriteLine("No Output data");
        return;
    }

    if (output.InfoData is null)
    {
        Console.WriteLine("No Info data");
        return;
    }

    Console.WriteLine($"ID:     {output.InfoData.Data!.id}");
    Console.WriteLine($"NUMBER: {output.InfoData.Data!.number}");
}

Output? badRequestResult = DeserializeJson(rawJsonBadRequest);
DumpState(badRequestResult);
DumpBadRequest(badRequestResult);

void DumpBadRequest(Output? output)
{
    if (output is null)
    {
        Console.WriteLine("No Output data");
        return;
    }

    if (output.InfoData is null)
    {
        Console.WriteLine("No Error data");
        return;
    }

    Console.WriteLine("Errors returned:");
    foreach (string error in output.InfoData.Errors!)
    {
        Console.WriteLine($" > {error}");
    }
}

void DumpState(Output? output)
{
    if (output is null)
    {
        Console.WriteLine("No Output data");
        return;
    }

    Console.WriteLine($"RESULT ID: {output.id}");
    Console.WriteLine($"MESSAGE: {output.msg}");
    Console.WriteLine($"TRANS_ID: {output.trans_id}");
}

Output? DeserializeJson(string rawJson)
{
    Output? result = JsonSerializer.Deserialize<Output>(rawJson);

    if (result is null)
        return null;

    result.InfoData = result?.id switch
    {
        200 => new Info
        {
            Data = result.info.Deserialize<Data>(jsonSerializerOptions)
        },
        400 => new Info
        {
            Errors = result.info.Deserialize<List<string>>(jsonSerializerOptions)
        },
        _ => null
    };

    return result;
}

public class Output
{
    public int id { get; set; }
    
    public string? msg { get; set; }
    
    public string? trans_id { get; set; }
    
    public JsonElement info { get; set; }

    [JsonIgnore]
    public Info? InfoData { get; set; }
}

public class Info
{
    public Data? Data { get; set; }
    public List<string>? Errors { get; set; }
}

public class Data
{
    public string? id { get; set; }
    public string? number { get; set; }
}

and the output:
RESULT ID: 200
MESSAGE: Successful
TRANS_ID: 415
ID:     41
NUMBER: 3889 is already exists
----------

RESULT ID: 400
MESSAGE: Bad Request
TRANS_ID: CLIENTAPI202306050146459
Errors returned:
 > state : value must be a valid string
 > city : value must be a valid string
 
Share this answer
 
v3
You can't: the two JSON data contain different schema: one requires a collection:
JSON
{
     "id": 400,
    "msg": "Bad Request",
    "trans_id": "CLIENTAPI202306050146459",
    "info": [
        "state : value must be a valid string",
        "city : value must be a valid string"
    ]
}
C#
public class Root
{
    public int id { get; set; }
    public string msg { get; set; }
    public string trans_id { get; set; }
    public List<string> info { get; set; }
}
And the other requires a single item:
JSON
{
    "id": 200,
    "msg": "Successful",
    "trans_id": "415",
    "info": {
        "id": "41",
        "number": "3889 is already exists"
    }
}

C#
public class Info
{
    public string id { get; set; }
    public string number { get; set; }
}

public class Root
{
    public int id { get; set; }
    public string msg { get; set; }
    public string trans_id { get; set; }
    public Info info { get; set; }
}
Since you cannot cast an Info class into an array of strings, you cannot use the same classes to deserialize both JSON snippets.
 
Share this answer
 
Comments
Graeme_Grant 14-Jun-23 0:28am    
Check my solution 😉

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900