Como a API Google Ads usa proto3 como formato de payload padrão, é importante entender algumas convenções e tipos de protobuf ao trabalhar com a API.
Campos opcionais
Muitos campos na API Google Ads são marcados como optional. Isso permite distinguir entre casos em que o campo tem um valor vazio e casos em que o servidor não enviou um valor para o campo. Esses campos se comportam como campos
regulares, mas também oferecem outros métodos para limpar o campo e
verificar se ele está definido.
Por exemplo, o campo Name do objeto Campaign é marcado como opcional. Portanto, você pode usar os seguintes métodos para trabalhar com esse campo.
// Get the name.
string name = campaign.Name;
// Set the name.
campaign.Name = name;
// Check if the campaign object has the name field set.
bool hasName = campaign.HasName();
// Clear the name field. Use this method to exclude Name field from
// being sent to the server in a subsequent API call.
campaign.ClearName();
// Set the campaign to empty string value. This value will be
// sent to the server if you use this object in a subsequent API call.
campaign.Name = "";
// This will throw a runtime error. Use ClearName() instead.
campaign.Name = null;
Campos repetidos
Uma matriz de campo é representada na API Google Ads como um
RepeatedField somente leitura.
Por exemplo, o campo url_custom_parameters de uma campanha é um campo repetido, então ele é representado como um RepeatedField<CustomParameter> somente leitura na biblioteca de cliente .NET. O RepeatedField implementa a interface IList<T>.
Há duas maneiras de preencher um campo RepeatedField.
Método AddRange
 Campaign campaign = new Campaign()
 {
     ResourceName = ResourceNames.Campaign(customerId, campaignId),
     Status = CampaignStatus.Paused,
 };
 // Add values to UrlCustomParameters using AddRange method.
 campaign.UrlCustomParameters.AddRange(new CustomParameter[]
 {
     new CustomParameter { Key = "season", Value = "christmas" },
     new CustomParameter { Key = "promocode", Value = "NY123" }
 });
 ```
Sintaxe do inicializador de coleção
// Option 1: Initialize the field directly.
Campaign campaign = new Campaign()
{
    ResourceName = ResourceNames.Campaign(customerId, campaignId),
    Status = CampaignStatus.Paused,
    // Directly initialize the field.
    UrlCustomParameters =
    {
        new CustomParameter { Key = "season", Value = "christmas" },
        new CustomParameter { Key = "promocode", Value = "NY123" }
    }
};
// Option 2: Initialize using an intermediate variable.
CustomParameter[] parameters = new CustomParameter[]
{
    new CustomParameter { Key = "season", Value = "christmas" },
    new CustomParameter { Key = "promocode", Value = "NY123" }
}
Campaign campaign1 = new Campaign()
{
    ResourceName = ResourceNames.Campaign(customerId, campaignId),
    Status = CampaignStatus.Paused,
    // Initialize from an existing array.
    UrlCustomParameters = { parameters }
};
Campos Oneof
Alguns campos na API Google Ads são marcados como oneof, o que significa que
o campo pode conter diferentes tipos, mas apenas um valor por vez. Os campos oneof são semelhantes ao tipo de união na linguagem de programação C.
A biblioteca .NET implementa campos oneof fornecendo uma propriedade para cada tipo de valor que pode ser mantido em um campo oneof, e todas as propriedades atualizam um campo de classe compartilhada.
Por exemplo, o campaign_bidding_strategy da campanha é marcado como um campo oneof. Esta classe é implementada da seguinte forma (código simplificado para brevidade):
public sealed partial class Campaign : pb::IMessage<Campaign>
{
    object campaignBiddingStrategy_ = null;
    CampaignBiddingStrategyOneofCase campaignBiddingStrategyCase_;
    public ManualCpc ManualCpc
    {
        get
        {
            return campaignBiddingStrategyCase_ == CampaignBiddingStrategyOneofCase.ManualCpc ?
                (ManualCpc) campaignBiddingStrategy_ : null;
        }
        set
        {
            campaignBiddingStrategy_ = value;
            campaignBiddingStrategyCase_ = CampaignBiddingStrategyOneofCase.ManualCpc;
        }
    }
    public ManualCpm ManualCpm
    {
        get
        {
            return campaignBiddingStrategyCase_ == CampaignBiddingStrategyOneofCase.ManualCpm ?
                (ManualCpm) campaignBiddingStrategy_ : null;
        }
        set
        {
            campaignBiddingStrategy_ = value;
            campaignBiddingStrategyCase_ = CampaignBiddingStrategyOneofCase.ManualCpm;
        }
    }
    public CampaignBiddingStrategyOneofCase CampaignBiddingStrategyCase
    {
        get { return campaignBiddingStrategyCase_; }
    }
}
Como as propriedades oneof compartilham armazenamento, uma atribuição pode substituir uma atribuição anterior, resultando em bugs sutis. Por exemplo,
Campaign campaign = new Campaign()
{
    ManualCpc = new ManualCpc()
    {
        EnhancedCpcEnabled = true
    },
    ManualCpm = new ManualCpm()
    {
    }
};
Nesse caso, campaign.ManualCpc agora é null, já que a inicialização do campo campaign.ManualCpm substitui a inicialização anterior de campaign.ManualCpc.
Conversão para outros formatos
Converter para o formato JSON
É possível converter objetos protobuf para o formato JSON e vice-versa. Isso é útil ao criar sistemas que precisam interagir com outros sistemas que exigem dados em formatos baseados em texto, como JSON ou XML.
GoogleAdsRow row = new GoogleAdsRow()
{
    Campaign = new Campaign()
    {
        Id = 123,
        Name = "Campaign 1",
        ResourceName = ResourceNames.Campaign(1234567890, 123)
    }
};
// Serialize to JSON and back.
string json = JsonFormatter.Default.Format(row);
row = GoogleAdsRow.Parser.ParseJson(json);
Converter em bytes
É possível serializar um objeto em bytes e vice-versa. A serialização binária é mais eficiente em termos de memória e armazenamento do que o formato JSON.
GoogleAdsRow row = new GoogleAdsRow()
{
    Campaign = new Campaign()
    {
        Id = 123,
        Name = "Campaign 1",
        ResourceName = ResourceNames.Campaign(1234567890, 123)
    }
};
// Serialize to bytes and back.
byte[] bytes = row.ToByteArray();
row = GoogleAdsRow.Parser.ParseFrom(bytes);