Как обращаться с API. Результат имеет ответ двух типов, подобный этому С#

Моя программа вызывает API, который реагирует по-разному, в зависимости от результата операции.

Как я могу справиться с этим в коде?

Ответ на успех

{
"status": "OK",
"message": {
"name": "HELLO NAME",
"id": "3171024302821001",
"pob": "GARESSI SUPPA",
"dob": "01-01-1961",
"gender": "LAKI-LAKI",
"address": "BTN UNHALU BLOK C NO. 28",
"rt": "006",
"rw": "003",
"village": "KAMBU",
"district": "KAMBU",
"religion": "ISLAM",
"marital_status": "KAWIN",
"work": "PEGAWAI NEGERI SIPIL (PNS)",
"nationnality": "WNI",
"city": "KOTA KENDARI",
"province": "SULAWESI TENGGARA"
}
}

Ответ на неудачу

{
"status": "FAIL",
"message": "check input image and retry"
}

я использую модель linq в С#

моя модель С#

public class IziDataKtpOcrResponseMessage
{
    public string Status { get; set; }

    public IziDataKtpOcrResponseMessageData message;
}

тогда это мой код для сбора сообщений

            iziDataKtpOcrResponseMessage = JsonConvert.DeserializeObject<IziDataResponseMessage>(iziDataKtpOcrResponse);

Я использую модель linq и Newtonsoft.Json для этого ответа, но когда я получаю ответ «не удалось», моя модель не поддерживает этот результат.

Возвращаются ли разные ответы с разными кодами состояния HTTP? Если это так, вы можете использовать это, чтобы определить, содержит ли ответ сообщение об ошибке или может ли быть десериализован в соответствующий объект.

phuzi 24.06.2024 17:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Используйте дискриминируемый союз, например OneOf<>https://github.com/mcintyre321/OneOf

Вот так:

sealed class GotPersonalDetailsResult
{
    public GotPersonalDetailsResult( String name, String id, String pob, etc... )
    {
        this.Name = name;
        this.Id   = id;
    }

    public String Name { get; }
    public String Id   { get; }
    // etc
}

sealed class FailureResult
{
    public FailureResult( String status, String message )
    {
        this.Status  = status;
        this.Message = message ;
    }

    public String Status  { get; }
    public String Message { get; }
}

С вашим методом обслуживания, например:

using OneOf;

public class RandomPeopleSearchClient
{
    public async Task< OneOf<GotPersonalDetails,FailureResult> > FindRandomPersonAsync( CancellationToken cancellationToken = default )
    {
        using( HttpClient hc = this.hcf.CreateClient() )
        {
            // etc

            if ( httpResponse.Status == 200 && isJsonResponse )
            {
                if ( TryParseGotPersonalDetailsResult( out GotPersonalDetailsResult ok )  )
                {
                    return ok; // <-- This is allowed due to implicit conversion from X or Y in OneOf<X,Y>
                }
                else if ( TryParseFailureResult( out FailureResult whoops )  )
                {
                    return whoops;
                }
            }

            // Otherwise, this is exceptional, so throwing is fine:

            throw new RandomPeopleSearchClientException( "Expected either a GotPersonalDetailsResult or a FailureResult but encountered an unexpected result", /* details-from-response-go-here */ );
        }
    }
}

И потребляется так:

RandomPeopleSearchClient client = ...

OneOf<GotPersonalDetails,FailureResult> result = await client.FindRandomPersonAsync();
if ( result.TryPickT0( out GotPersonalDetailsResult ok, out FailureResult  failed )
{
    // Use only `ok` here
}
else
{
    // Use only `failed` here
}

Обратите внимание, что вы не ограничены двумя взаимоисключающими типами результатов: тип OneOf<> поддерживает до 8 различных типов.

Когда вы используете OneOf<X,Y,Z> 3-го типа (или более), метод TryPickT0() возвращает остаток n-1 в качестве второго параметра out, что позволяет вам безопасно использовать else if C#, не опасаясь случайного разыменования невозможного значения результата, например:

OneOf<X,Y,Z> choiceOf3 = ...
if ( choiceOf3.TryPickT0( out X x, out OneOf<Y,Z> yz )
{
    // Use only `x` here
}
else if ( if ( yz.TryPickT0( out Y y, out Z z ) )
{
    // Use only `y` here
}
else
{
    // Use only `z` here
}

В нем также есть другие методы Match и Switch в стиле FP, которые вы можете использовать, чтобы не беспокоиться об исчерпывающих блоках if.

Ответ принят как подходящий

Вы можете проверить значение поля JSON (статус) перед десериализацией в определенный класс.

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

var jsonString = @"
{
    ""status"": ""FAIL"",
    ""message"": ""check input image and retry""
}
";

var jobj = JsonConvert.DeserializeObject<JObject>(jsonString);
var status = jobj["status"].ToString();
if (status == "FAIL")
{
    var errorResponse = JsonConvert.DeserializeObject<ErrorResponse>(jsonString);
}
else if (status == "OK")
{
    var successResponse = JsonConvert.DeserializeObject<SuccessResponse>(jsonString);
}


public class Message
{
    public string name { get; set; }
    public string id { get; set; }
    public string pob { get; set; }
    public string dob { get; set; }
    public string gender { get; set; }
    public string address { get; set; }
    public string rt { get; set; }
    public string rw { get; set; }
    public string village { get; set; }
    public string district { get; set; }
    public string religion { get; set; }
    public string marital_status { get; set; }
    public string work { get; set; }
    public string nationnality { get; set; }
    public string city { get; set; }
    public string province { get; set; }
}

public class SuccessResponse
{
    public string status { get; set; }
    public Message message { get; set; }
}
public class ErrorResponse
{
    public string status { get; set; }
    public string message { get; set; }
}

хо, если я приму сообщение об успешном ответе вот так? var status = jobj["status"].ToString();

MursyidinAdnan 24.06.2024 11:22

Другие вопросы по теме