1

LightSpeed API から連絡先を呼び出しています。

クライアント「A」の詳細を要求すると、JSON には関連する電子メールの次の内容が含まれます。

{
    "Emails": {
        "ContactEmail": {
            "address": "clienta@yahoo.com",
            "useType": "Primary"
        }
    }
}

クライアント「B」の詳細を要求すると、JSON にはこの関連する電子メールの次の内容が含まれます

{
    "Emails": {
        "ContactEmail": [{
                "address": "clientb1@gmail.com",
                "useType": "Primary"
            }, {
                "address": "clientb2@gmail.com",
                "useType": "Secondary"
            }
        ]
    }
}

私が正しければ、返される「電子メール」が1つしかなくても、最初の応答は配列でなければならないと思います...? システムでは、顧客がレコードに複数の電子メールを含めることが許可されているためです。

これが、デシリアライズしようとしているクラスです。クライアント「B」では完全に機能しますが、クライアント「A」では失敗します

public class GetCustomersResponse
{
    public Attributes attributes { get; set; }
    public List<Customer> Customer { get; set; }
}

public class Attributes
{
    public string count { get; set; }
}

public class Customer
{
    public string customerID { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }
    public string title { get; set; }
    public string company { get; set; }
    public string companyRegistrationNumber { get; set; }
    public string vatNumber { get; set; }
    public DateTime createTime { get; set; }
    public DateTime timeStamp { get; set; }
    public string archived { get; set; }
    public string contactID { get; set; }
    public string creditAccountID { get; set; }
    public string customerTypeID { get; set; }
    public string discountID { get; set; }
    public string taxCategoryID { get; set; }
    public Contact Contact { get; set; }
}

public class Contact
{
    public string contactID { get; set; }
    public string custom { get; set; }
    public string noEmail { get; set; }
    public string noPhone { get; set; }
    public string noMail { get; set; }
    public Addresses Addresses { get; set; }
    public Phones Phones { get; set; }
    public Emails Emails { get; set; }
    public string Websites { get; set; }
    public DateTime timeStamp { get; set; }
}

public class Addresses
{
    public Contactaddress ContactAddress { get; set; }
}

public class Contactaddress
{
    public string address1 { get; set; }
    public string address2 { get; set; }
    public string city { get; set; }
    public string state { get; set; }
    public string zip { get; set; }
    public string country { get; set; }
    public string countryCode { get; set; }
    public string stateCode { get; set; }
}

public class Phones
{
    public List<Contactphone> ContactPhone { get; set; }
}

public class Contactphone
{
    public string number { get; set; }
    public string useType { get; set; }
}

public class Emails
{
    public List<Contactemail> ContactEmail { get; set; }
}

public class Contactemail
{
    public string address { get; set; }
    public string useType { get; set; }
}

LightSpeed に API を変更してもらうのが見えないので、私のクラスで動作するように 1 つの電子メール アドレスを持つクライアントを取得する方法を誰か提案できますか?

どんな助けでも大歓迎です。

アップデート:

与えられた助けを借りて、いくつかの作業コードに非常に近づきました。

これは、カスタムjsonコンバーター用に私が持っているものです:

public class ContactEmailJsonConverter : JsonConverter<List<ContactEmail>>
{
    public override List<ContactEmail> Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options)
    {
        try
        {
            if (reader.TokenType == JsonTokenType.StartArray)
            {
                return (List<ContactEmail>)JsonSerializer
                    .Deserialize(ref reader, typeToConvert, options);
            }
            else if (reader.TokenType == JsonTokenType.StartObject)
            {
                var email = (ContactEmail)JsonSerializer
                    .Deserialize(ref reader, typeof(ContactEmail), options);
                return new List<ContactEmail>(capacity: 1) { email };
            }
            else
            {
                throw new InvalidOperationException($"got: {reader.TokenType}");
            }
        }
        catch(Exception ex)
        {
            return null;
        }
    }

    public override void Write(Utf8JsonWriter writer, List<ContactEmail> value, JsonSerializerOptions options)
    {
        if ((value is null) || (value.Count == 0))
        {
            JsonSerializer.Serialize(writer, (ContactEmail)null, options);
        }
        else if (value.Count == 1)
        {
            JsonSerializer.Serialize(writer, value[0], options);
        }
        else
        {
            JsonSerializer.Serialize(writer, value, options);
        }
    }
}

しかし、メールをまったく持っていないように見える連絡先を見つけました..そして、LightSpeed によって返される JSON は次のようになります。

 "Emails":""

そして、私が書いたコンバーターコードを壊しています。この完全に空のオブジェクトを処理する方法がわかりません。

4

2 に答える 2

0

必要なのはコンバーターだと思います。これは手っ取り早いので 100% ではありませんが、かなり近いものになると思います (別の方向に進む必要はありませんでしたが、実装しただけReadです。

Emailsこれを使用するには、クラスをコンバーターでマークアップします。

public class Emails
{
    [JsonConverter(typeof(ContactEmailJsonConverter))]
    public Contactemail[] ContactEmail { get; set; }
}

そして、そのようにコンバーターを書きます。私がここで行ったことは、基本的に[最初に探して、そこにない場合は、逆シリアル化する前にラップすることでした。

public class ContactEmailJsonConverter : JsonConverter<Contactemail[]>
{
    public override Contactemail[] Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) =>
        {
            string content = reader.GetString();
            if(!content.Trim().StartsWith("["))
            {
                content = $"[{content}]";
            }
            return JsonSerializer.Deserialize<Contactemail[]>(content);
        };

    public override void Write(
        Utf8JsonWriter writer,
        Contactemail[] cotactEmails,
        JsonSerializerOptions options) =>
            throw new NotImplementedException();
}

おそらくより堅牢にすることができますが、これで始めることができます。

注:コンバーター側ではもう少し複雑Contactemail[]だと思うので、タイプをに更新しました。List<T>以下にリンクされているドキュメントでは、「Factory パターン」を使用するように述べられており、例が示されているため、それに固執したい場合List<T>は、代わりにそれに従うことができます。

その他のドキュメント: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-5-0

于 2021-05-04T14:21:09.870 に答える