Конвертировать Google-Ads API GoogleAdsRow в json?

Я запрашиваю Google Ads API и нужно сохранить результаты как JSON. Каков наилучший способ конвертировать тип GoogleAdsRow в json?

Результат работы приложения Google Ads выглядит следующим образом (идентификаторы кампании и клиента являются поддельными):

campaign {
  resource_name: "customers/752830100/campaigns/22837002"
  id {
    value: 22837002
  }
  name {
    value: "test"
  }
}
metrics {
  clicks {
    value: 51
  }
  impressions {
    value: 33
  }
}

тип = <class 'google.ads.googleads_v1.types.GoogleAdsRow'>

5 ответов

В Google.protobuf есть метод json_format, который может делать именно это. Ниже приведен пример кода, который поможет:

# Import the method 
from google.protobuf import json_format
import json

# Query the Ads API, 
ga_service = client.get_service('GoogleAdsService', version='YOUR_VERSION')
query = ('YOUR_QUERY')

# Response as an iterator made up of GoogleAdsRow  
response = ga_service.search(customer_id, query)

# Converting each of the GoogleAdsRow to json
for row in response : 
    json_str = json_format.MessageToJson(row)
    d = json.loads(json_str)

Прямо сейчас я тоже ищу ту же проблему. Я нашел один обходной путь - использовать CustomEncoder в json.dumps. Вот пример:

class CustomEncoder(json.JSONEncoder):
def default(self, obj):
    if isinstance(obj, (google.protobuf.wrappers_pb2.StringValue,
                        google.protobuf.wrappers_pb2.Int64Value, 
                        google.protobuf.wrappers_pb2.DoubleValue)):
        return obj.value

    elif isinstance(obj, google.protobuf.pyext._message.RepeatedCompositeContainer):
        data = []
        try:
            while True:
                item = obj.pop()
                data.append(self.default(item))
        except IndexError:
            return data

    elif isinstance(obj, google.ads.google_ads.v1.proto.common.custom_parameter_pb2.CustomParameter):
        return { 
                self.default(obj.key): self.default(obj.value) 
                }
return json.JSONEncoder.default(self, obj)

Используйте указанный выше кодировщик в json.dumps(data, cls=CustomEncoder)

Это единственное решение, с которым я до сих пор пришел. Обновлю, если найду лучшее решение.

Отредактировано: найдено решение. Вот класс New Encoder.

class GoogleProtoEncoder(json.JSONEncoder):
"""
Custom JSON Encoder for GoogleAdsRow. 

Usage: json.dumps(data, cls=GoogleProtoEncoder)
"""
def default(self, obj):
    """
    Overriden method. When json.dumps() is called, it actually calls this method if 
    this class is specified as the encoder in json.dumps().
    """
    if isinstance(obj, google.protobuf.message.Message) and hasattr(obj, 'value'):
        # This covers native data types such as string, int, float etc
        return obj.value

    elif isinstance(obj, google.protobuf.pyext._message.RepeatedCompositeContainer):
        # This is basically for python list and tuples
        data = []
        try:
            while True:
                item = obj.pop()
                data.append(self.default(item))
        except IndexError:
            return data

    elif isinstance(obj, google.ads.google_ads.v1.proto.common.custom_parameter_pb2.CustomParameter):
        # Equivalent to python dictionary
        return { 
                self.default(obj.key): self.default(obj.value) 
                }

    elif isinstance(obj, google.protobuf.message.Message):
        # All the other wrapper objects which can have different fields.
        return {key[0].name: getattr(obj, key[0].name) for key in obj.ListFields()}

    return json.JSONEncoder.default(self, obj)

Спасибо.

Если вам не нужно использовать SDK, другой способ получить json - это запросить API, отправив напрямую почтовый запрос, который вернет ответ json:

r = requests.post('https://googleads.googleapis.com/v3/customers/YOUR_CUSTOMER_ID/googleAds:searchStream', 
                 headers={'Authorization': f'Bearer {access_token}',
                         'developer-token' : developer_token,
                         'login-customer-id' : 'YOUR_CUSTOMER_ID',
                         'Content-Type': 'application/json'},
                params={"query" : query})

Теперь вы можете использовать собственные вспомогательные методы protobuf, как описано здесь:https://developers.google.com/google-ads/api/docs/client-libs/python/library-version-10#wrapped_versus_native_protobuf_messages

      campaign = client.get_type("Campaign")
json = type(campaign).to_json(campaign)
campaign = type(campaign).from_json(json)

Шаг 1. Импортируйте эту библиотеку

      from google.ads.googleads.errors import GoogleAdsException

Шаг 2. Отправьте запрос

      keyword_ideas = keyword_plan_idea_service.generate_keyword_ideas(
    request=request
)

Шаг 3. Преобразуйте ответ в json

      keyword_ideas_json = MessageToDict(keyword_ideas)

Шаг 4. Делайте с этим все, что хотите json

      print(keyword_ideas_json)

Примечание. Это может быть attribute error: "DESCRIPTOR"ошибка, так что посмотрите на этот ответ: здесь

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