Cómo trabajar con tipos de Protobuf

Dado que la API de Google Ads usa Protobuf como su formato de carga útil predeterminado, es importante comprender algunas convenciones y tipos de Protobuf cuando se trabaja con la API.

Campos opcionales

Muchos campos de la API de Google Ads están marcados como optional. Esto te permite distinguir entre los casos en los que el campo tiene un valor vacío y los casos en los que el servidor no envió un valor para el campo. Estos campos se comportan como campos normales, excepto que también proporcionan métodos adicionales para borrar el campo y verificar si está configurado.

Por ejemplo, el campo Name del objeto Campaign está marcado como opcional. Por lo tanto, puedes usar los siguientes métodos para trabajar con este 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;

Tipos repetidos

Un array de campos se representa en la API de Google Ads como un RepeatedField de solo lectura.

Un ejemplo es que el campo url_custom_parameters de una campaña sea un campo repetido, por lo que se representa como un RepeatedField<CustomParameter> de solo lectura en la biblioteca cliente de .NET.

RepeatedField implementa la interfaz IList<T>.

Existen dos maneras de propagar un campo RepeatedField.

Versión anterior de C#: Agrega valores con el método AddRange

A continuación, se muestra un ejemplo.

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" }
});

Versiones más recientes de C#: Usa la sintaxis del inicializador de colecciones

// 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 }
};

Tipos de OneOf

Algunos campos de la API de Google Ads están marcados como campos OneOf, lo que significa que el campo puede contener diferentes tipos, pero solo un valor a la vez. Los campos OneOf son similares al tipo de unión en C.

La biblioteca de .NET implementa campos OneOf proporcionando una propiedad para cada tipo de valor que se puede contener en un campo OneOf y todas las propiedades que actualizan un campo de clase compartido.

Por ejemplo, el campaign_bidding_strategy de la campaña se marca como un campo OneOf. Esta clase se implementa de la siguiente manera (se simplificó el código para que sea más breve):

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_; }
    }
}

Dado que las propiedades OneOf comparten el almacenamiento, una asignación puede reemplazar una anterior, lo que genera errores sutiles. Por ejemplo:

Campaign campaign = new Campaign()
{
    ManualCpc = new ManualCpc()
    {
        EnhancedCpcEnabled = true
    },
    ManualCpm = new ManualCpm()
    {

    }
};

En este caso, campaign.ManualCpc ahora es null, ya que inicializar el campo campaign.ManualCpm reemplaza la inicialización anterior de campaign.ManualCpc.

Conversión a otros formatos

Puedes convertir fácilmente objetos protobuf a formato JSON y viceversa. Esto es útil cuando se compilan sistemas que deben interactuar con otros sistemas que requieren datos en formatos basados en texto, como JSON o 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);

También puedes serializar un objeto a bytes y viceversa. La serialización binaria es más eficiente en términos de memoria y almacenamiento que el 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);