2015-03-24 3 views
0

Я использую API, что среди прочего есть эти два ответа:Deserialize JSON ответ

{ 
    "enrollDeviceErrorResponse": { 
     "errorCode": "GRX-1056", 
     "errorMessage": "DEP Reseller ID missing. 
     Enter a valid DEP Reseller ID and resubmit your request." 
    } 
} 

или

{ 
    "enrollDeviceErrorResponse": [ 
     { 
      "errorCode": "GRX-1056", 
      "errorMessage": "DEP Reseller ID missing. 
      Enter a valid DEP Reseller ID and resubmit your request." 
     }, 
     { 
      "errorCode": "DEP-ERR-3003", 
      "errorMessage": "Order information missing. T 
      he transaction needs to have one or more valid orders. 
      Enter valid orders and resubmit your request." 
     }, 
     { 
      "errorCode": "DEP-ERR-3001", 
      "errorMessage": "Transaction ID missing. 
      Enter a valid transaction ID and resubmit your request." 
     } 
    ] 
} 

Я создал некоторые классы, которые могут десериализации в этих ответов:

public class EnrollDeviceErrorRoot 
{ 
    public EnrollDeviceErrorRoot() 
    { 
     this.EnrollDeviceErrorResponse = new EnrollDeviceErrorResponse(); 
    } 

    public EnrollDeviceErrorResponse EnrollDeviceErrorResponse { get; set; } 
} 

public class EnrollDeviceErrorRoot 
{ 
    public EnrollDeviceErrorRoot() 
    { 
     this.EnrollDeviceErrorResponse = new EnrollDeviceErrorResponse(); 
    } 

    public EnrollDeviceErrorResponse EnrollDeviceErrorResponse { get; set; } 
} 

public class EnrollDeviceErrorResponse 
{ 
    public string ErrorCode { get; set; } 

    public string ErrorMessage { get; set; } 
} 

У меня трудное время подходит с хорошим способом определить, какой из моих классов я должен использовать в зависимости на ответ. Я в настоящее время этот неисправный код:

var multipleErrors = JsonConvert.DeserializeObject<EnrollDeviceErrorsRoot>(response); 

if (multipleErrors.EnrollDeviceErrorResponse != null && multipleErrors.EnrollDeviceErrorResponse.Any()) 
{ 
    this.StatusCode = multipleErrors.EnrollDeviceErrorResponse.Select(x => x.ErrorCode).Aggregate((a, b) => a + ", " + b); 
    this.StatusMessage = multipleErrors.EnrollDeviceErrorResponse.Select(x => x.ErrorMessage).Aggregate((a, b) => a + Environment.NewLine + b); 
    this.HasErrors = true; 

    return; 
} 

var singleError = JsonConvert.DeserializeObject<EnrollDeviceErrorRoot>(response); 

if (!string.IsNullOrEmpty(singleError.EnrollDeviceErrorResponse.ErrorCode)) 
{ 
    this.StatusCode = singleError.EnrollDeviceErrorResponse.ErrorCode; 
    this.StatusMessage = singleError.EnrollDeviceErrorResponse.ErrorMessage; 
    this.HasErrors = true; 

    return; 
} 

Ошибка из кода выше:

Newtonsoft.Json.JsonSerializationException : Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Atea.Dep.Core.Service.Models.EnrollDeviceErrorResponse]' 
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. 

Как другие люди обработки этой deserializations из ответов, когда они не знают, что они получают от сервера? Я мог бы, конечно, просто взглянуть на исходный ответ и определить этот путь, но есть ли другие более чистые способы сделать это? Я не могу изменить API, я понятия не имею, почему просто не может быть ответа со списком с одной или несколькими ошибками.

ответ

2

Вы можете использовать

JObject.Parse(response)["enrollDeviceErrorResponse"].Type 

определить тип ответа. В первом случае это будет obect, во 2-м массиве. Тогда будет легко продолжить надлежащую десериализацию.

+0

Спасибо, что работал отлично! – Pelle

1

Вы можете использовать что-то вроде этого:

var output; 
dynamic jObject = JsonConvert.DeserializeObject (outputAPI); 
bool isArray = jObj.enrollDeviceErrorResponse.Type == JTokenType.Array; 
bool isObject = jObj.enrollDeviceErrorResponse.Type == JTokenType.Object; 
if(isObject) 
    output = JsonConvert.DeserializeObject<EnrollDeviceErrorResponse>(outputAPI); 
//else you will use the other class to deserialize the object