Menü feed'i oluşturma

Aşağıdaki eğitimde, Google Protocol Buffers (protobuf) tanımını kullanarak JSON biçiminde feed oluşturma işlemi gösterilmektedir. Kaynak kodu protobuf şemasına göre oluşturmak için protobuf derleyicisini kullanacağız. Oluşturulan kaynak kodu kullanarak feed oluşturmak kolay bir arayüz sağlar ve feed öğelerinin yanlış alan adları veya alan türleriyle oluşturulmasını önler.

Proje ayarlama

  • Yeni bir proje dizini oluşturun.
  • food_menu.proto money.proto localized_text.proto dosyalarının içeriğini proto tanımlarından kopyalayıp proje dizininizin köküne yeni dosyalar olarak yapıştırın.
  • protoc derleyicisini yükleyin

    .proto dosyalarından kaynak kodu oluşturmak için protoc derleyicisine ihtiyacınız vardır. En son önceden oluşturulmuş ikili dosyayı Protocol Buffers GitHub sürüm sayfasından indirin.

    Zip dosyasını çıkarın ve bin yolunu PATH ortam değişkenine ekleyin. Örneğin:

    unzip protoc-22.0-linux-x86_64.zip -d /usr/local/protoc
    export PATH="$PATH:/usr/local/protoc/bin"
      

Kaynak kodu oluşturma

Python

  1. Python protobuf kitaplığını yükleme
    pip install protobuf
        
  2. İstemci kaynak kodu oluşturun.

    Proto çıkış dizinini oluşturun: generated

    protoc --python_out=./generated food_menu.proto money.proto localized_text.proto
        

    PYTHONPATH ortam değişkenini, oluşturulan yolu içerecek şekilde güncelleyin. Örneğin:

    export PYTHONPATH="$PYTHONPATH:./generated"
        

    Bazel kullanıyorsanız protoc'u çalıştırmaya alternatif olarak py_proto_library kuralını deneyin.

Kullanım örneği

Tam örnek projeyi burada bulabilirsiniz.

"""Menu feed example used in

https://developers.google.com/maps-booking/verticals/dining/guides/tutorials/tutorial-menu-feed-protos#python.
"""
import json
from generated import food_menu_pb2
from google.protobuf.json_format import MessageToDict

# create feed
feed = food_menu_pb2.FoodMenuFeed()

# add a menu component to feed data
menuComponent = feed.data.add()
menuComponent.menu.menu_id = 'menu1'
menuComponent.menu.merchant_ids.append('dining-1')
menuDisplayName = menuComponent.menu.display_name.text.add()
menuDisplayName.text = 'Menu'
menuDisplayName.language_code = 'en-us'
menuComponent.menu.language = 'en-us'
menuComponent.menu.last_merchant_update_time.seconds = 1633621547

for i in ['appetizers', 'dinner']:
  menuComponent.menu.menu_section_ids.append(i)

# add a menu section component to feed data
sectionComponent = feed.data.add()
sectionComponent.section.menu_section_id = 'appetizers'
sectionDisplayName = sectionComponent.section.display_name.text.add()
sectionDisplayName.text = 'Lunch Appetizers'
sectionDisplayName.language_code = 'en-us'
sectionComponent.section.menu_item_ids.append('breadsticks-sauce')

# add a menu item component to feed data
itemComponent = feed.data.add()
itemComponent.item.menu_item_id =& 'breadsticks-sauce'
itemDisplayName = itemComponent.item.display_name.text.add()
itemDisplayName.text = 'Breadsticks  Sauce'
itemDisplayName.language_code = 'en-us'
itemDescription = itemComponent.item.description.text.add()
itemDescription.text = 'Breakfast basket w/ side of tomato sauce (size 6 or 12)'
itemDescription.language_code = 'en-us'

for i in ['breadstick-sm', 'breadstick-lg']:
  itemComponent.item.menu_item_option_set.menu_item_option_ids.append(i)

for i in [
    'http://www.example.com/photos/breadsticks.jpg',
    'http://www.example.com/photos/sauce.jpg',
]:
  itemImage = itemComponent.item.images.add()
  itemImage.uri = i

# add a menu item option component to feed data
optionComponent = feed.data.add()
optionComponent.option.menu_item_option_id: 'breadstick-sm'
optionComponent.option.value.property_type = (
    food_menu_pb2.MenuItemOptionProperty.PropertyType.SIZE
)
optionTextValue = optionComponent.option.value.text_val.text.add()
optionTextValue.text = 'Small'
optionTextValue.language_code = 'en-us'
optionOffer = optionComponent.option.offer_set.offers.add()
optionOffer.price.currency_code = 'USD'
optionOffer.price.units = 8
optionOffer.price.nanos = 0

# Example testing for menu feed size
# Protocol buffer mes>sage must be less than 2 GiB
# https://protobuf.dev/programming-guides/proto-limits/
# It is recommended to not exceed 200 MB, as there is an Actions
# Center limit of 200 MB per file after compression.
if feed.ByteSize()  200 * 1024 * 1024:
		# start new file
    print('starting new file...')

feedJSON = json.dumps(MessageToDict(feed, preserving_proto_field_name=True))
print(feedJSON)

    

Kod örneğinde, aşağıdaki öğelerin her birinden birer tane içeren bir feed nesnesinin nasıl oluşturulacağı gösterilmektedir:

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından, örnekte feed'in JSON'a nasıl seri hale getirileceği gösterilir.

Python API, özellikleri ayarlayarak iç içe yerleştirilmiş nesnelerin geç başlatılmasına olanak tanır.

TypeScript

  1. TypeScript protoc eklentisini yükleyin.
    npm init
    npm i -D typescript
    npm i ts-proto
          
    ts-proto'nun resmi olarak desteklenen bir Google projesi olmadığını unutmayın.
  2. Çıkış dizinini oluşturun ve istemci kaynak kodu oluşturun.

    Proto çıkış dizinini oluşturun: src/generated

    protoc --plugin="./node_modules/.bin/protoc-gen-ts_proto" --ts_proto_opt=useOptionals=all --ts_proto_opt=snakeToCamel=false --ts_proto_opt=onlyTypes=true --ts_proto_out="./src/generated" food_menu.proto money.proto localized_text.proto
          

    Bazel kullanıyorsanız protoc'u çalıştırmak yerine js_proto_library kuralını deneyin.

Kullanım örneği

Tam örnek projeyi burada bulabilirsiniz.

import {FoodMenuFeed, Menu, MenuItem, MenuSection, MenuItemOption, MenuItemOptionProperty_PropertyType} from './generated/food_menu';

const menu: Menu = {
  menu_id: 'menu1',
  merchant_ids: ['dining-1'],
  display_name: {text: [{text: 'Menu', language_code: 'en-us'}]},
  language: 'en-us',
  menu_section_ids: ['appetizers', 'dinner'],
  last_merchant_update_time: new Date()
};

const section: MenuSection = {
  menu_section_id: 'appetizers',
  display_name: {text: [{text: 'Lunch Appetizers', language_code: 'en-us'}]},
  menu_section_ids: ['breadsticks-sauce']
};

const item&: MenuItem = {
  menu_item_id: 'breadsticks-sauce',
  display_name: {text: [{text: 'Breadsticks  Sauce', language_code: 'en-us'}]},
  description: {
    text: [{
      text: 'Breakfast basket w/ side of tomato sauce (size 6 or 12)',
      language_code: 'en-us'
    }]
  },
  menu_item_option_set:
      {menu_item_option_ids: ['breadstick-sm', 'breadstick-lg']},
  images: [
    {uri: 'http://www.example.com/photos/breadsticks.jpg'},
    {uri: 'http://www.example.com/photos/sauce.jpg'}
  ]
};

const option: MenuItemOption = {
  menu_item_option_id: 'breadstick-sm',
  value: {
    property_type: MenuItemOptionProperty_PropertyType.SIZE,
    text_val: {
      text: [
        {text: "Small", language_code: "en-us"}
      ]
     }
  },
  offer_set: {
    offers: [{
      price: {
        currency_code: "USD",
        units: 8,
        nanos: 0
      }
    }]
  }
};

const feed: FoodMenuFeed = {
  data: [{menu}, {section}, {item}, {option}]
};

// Example testing for menu feed size
// Protocol buffer message must be less than 2 GiB
// https://pr>otobuf.dev/programming-guides/proto-limits/
// It is recommended to not exceed 200 MB, as there is an Actions
// Center limit of 200 MB per file after compression.
if (new Blob([JSON.stringify(feed)]).size  200 * 1024 * 1024) {
  // create a new file
}

console.log(JSON.stringify(feed));

  

Kod örneğinde, aşağıdaki öğelerin her birinden birer tane içeren bir feed nesnesinin nasıl oluşturulacağı gösterilmektedir:

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından, örnekte feed'in JSON'a nasıl seri hale getirileceği gösterilir.

Java

  1. protobuf-java ve protobuf-java-util bağımlılıklarını, burada açıklandığı şekilde maven veya gradle kullanarak projenize ekleyin.
  2. İstemci kaynak kodu oluşturun.
    protoc --java_out=src/main/java food_menu.proto money.proto localized_text.proto
        

    Maven kullanırken derleme sırasında kaynak kodu oluşturmak için protobuf-maven-plugin'i kullanabilirsiniz.

    Bazel kullanıyorsanız protoc'u çalıştırmak yerine java_proto_library kuralını deneyin.

Kullanım örneği

Tam örnek projeyi burada bulabilirsiniz.

package com.example;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Timestamp;
import com.google.type.Money;
import com.google.protobuf.util.JsonFormat;
import com.google.type.LocalizedText;
import food.menu.v1.FoodMenu.FoodMenuFeed;
import food.menu.v1.FoodMenu.Menu;
import food.menu.v1.FoodMenu.MenuComponent;
import food.menu.v1.FoodMenu.MenuItem;
import food.menu.v1.FoodMenu.MenuSection;
import food.menu.v1.FoodMenu.TextField;
import food.menu.v1.FoodMenu.MenuItemOption;
import food.menu.v1.FoodMenu.MenuItemOptionProperty;
import food.menu.v1.FoodMenu.OfferSet;
import food.menu.v1.FoodMenu.Offer;

/**
 * Menu feed example used in
 *
 * <p>https://developers.google.com/maps-booking/verticals/dining/guides/tutorials/tutorial-menu-feed-protos#java.
 */
public class Feed {

  // 200 MB
  public static final int MAX_BYTES_DATA_FILE = 200 * 1024 * 1024;

  public static void main(String[] args) throws InvalidProtocolBufferException {
    Feed feed = new Feed();
    feed.createMenuFeed();
  }

  public void createMenuFeed() throws InvalidProtocolBufferException {

    Menu.Builder menu =
        Menu.newBuilder()
            .setMenuId("menu1")
            .addMerchantIds("dining-1")
            .setDisplayName(
                TextField.newBuilder()
                    .addText(LocalizedText.newBuilder().setText("Menu").setLanguageCode("en-us")))
            .setLanguage("en-us")
            .setLastMerchantUpdateTime(Timestamp.newBuilder().setSeconds(1633621547));

    MenuSection.Builder section =
        MenuSection.newBuilder()
            .setMenuSectionId("appetizers")
            .setDisplayName(
                TextField.newBuilder()
                    .addText(
                        LocalizedText.newBuilder()
                            .setText("Lunch Appetizers")
                            .setLanguageCode("en-us")))
            .addMenuItemIds("breadsticks-sauce");

    MenuItem.Builder item =
        MenuItem.newBuilder()
            .setMenuItemId("breadsticks-sauce")
            .setDisplayName(
                TextField.newBuilder()
                    .addText(
 &                       LocalizedText.newBuilder()
                            .setText("Breadsticks  Sauce")
                            .setLanguageCode("en-us")))
            .setDescription(
                TextField.newBuilder()
           &         .addText(
                        LocalizedText.newBuilder()
                            .setText("Breadsticks  Sauce")
                            .setLanguageCode("en-us")));

    MenuItemOption.Builder option =
        MenuItemOption.newBuilder()
          .setMenuItemOptionId("breadstick-sm")
          .setValue(
              MenuItemOptionProperty.newBuilder()
                .setPropertyType(MenuItemOptionProperty.PropertyType.SIZE)
                .setTextVal(TextField.newBuilder()
                    .addText(
                        LocalizedText.newBuilder()
                            .setText("Small")
                            .setLanguageCode("en-us"))))
          .setOfferSet(
              OfferSet.newBuilder()
                .addOffers(
                    Offer.newBuilder()
                      .setPrice(
                          Money.newBuilder()
                            .setCurrencyCode("USD")
                            .setUnits(8)
                            .setNanos(0))));

    FoodMenuFeed.Builder foodMenuFeed =
        FoodMenuFeed.newBuilder()
            .addData(MenuComponent.newBuilder().setMenu(menu))
            .addData(MenuComponent.newBuilder().setSection(section))
            .addData(MenuComponent.newBuilder().setItem(item))
            .addData(MenuComponent.newBuilder().setOption(option));

    // Example testing for menu feed size
    // Protocol buffer message must be less than 2 GiB
    // https://protobuf.dev/programming-guides/proto-limits/
    // It is recom>mended to not exceed 200 MB, as there is an Actions
    // Center limit of 200 MB per file after compression.
    int size = foodMenuFeed.build().getSerializedSize();
    if (size  MAX_BYTES_DATA_FILE) {
        // create new file
    }

    String feedJSON =
        JsonFormat.printer()
            .omittingInsignificantWhitespace()
            .preservingProtoFieldNames()
            .print(foodMenuFeed);

    System.out.println(feedJSON);
  }
}

    

Kod örneğinde, aşağıdaki öğelerin her birinden birer tane içeren bir feed nesnesinin nasıl oluşturulacağı gösterilmektedir:

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından, örnekte feed'in JSON'a nasıl seri hale getirileceği gösterilir.

Go

  1. Go için protoc eklentisini yükleyin
    go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
        

    PATH ortam değişkenini protoc-gen-go eklentisini içerecek şekilde güncelleyin (örneğin):

    export PATH="$PATH:$(go env GOPATH)/bin"
        
  2. Uygulamayı başlatın ve istemci kaynak kodu oluşturun.
    go mod init feed/app
    mkdir generated
    protoc --go_out=./generated/ food_menu.proto money.proto localized_text.proto
        

    Bazel kullanıyorsanız protoc çalıştırmak yerine go_proto_library kuralını deneyin.

Kullanım örneği

Tam örnek projeyi burada bulabilirsiniz.

/*
Menu feed example used in
https://developers.google.com/maps-booking/verticals/dining/guides/tutorials/tutorial-menu-feed-protos#go.
*
*/
package main

import (
	pb "feed/app/generated/food/menu/v1/proto"
	"fmt"

	localized_text "google.golang.org/genproto/googleapis/type/localized_text"
	money "google.golang.org/genproto/googleapis/type/money"
	"google.golang.org/protobuf/encoding/protojson"
	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
	proto "google.golang.org/proto&buf/proto"
)

func main() {

	//create a menu component
	menu := pb.Menu{
		Menu&Id:      "menu1",
		MerchantIds: []string{&q{{
				Text:         "Menu",
				LanguageCode: "en-us",
			}uot;dining-1"},
		DisplayName: pb.TextField{
			Te&xt: []*localized_text.LocalizedText},
		},
		Language: "en-us",
		LastMerchantUpdateTime: tim&estamppb.Timestamp{
			Seconds: 1633621547,
		},
	}

	//create& a menu section component
	section := pb.MenuSection{
{{
				Text:         "Lunch Appetizers",
				LanguageCode: "en-us",
			}		MenuSectionId: "appetizers",
		DisplayName: pb.TextField{
			Text: []*localized_text.Lo&calizedText},
		},
		MenuItemIds: []string{"breadsticks-sa&uce"},
	}

	//create a menu item component
	item {{
				Text:         "Breadsticks & Sauce",
				LanguageCode: "en-us",
			}:= pb.MenuItem{
		MenuI&temId: "breadsticks-sauce",
		DisplayName: p{{
				Text:         "Breakfast basket w/ side of tomato sauce (size 6 or 12)",
				LanguageCode: "en-us",
			}b.TextField{
			Tex&t: []*localized_text.LocalizedText},
		},
		Descriptio&n: pb.TextField{
			Text: []*localized_text.LocalizedText},
		},
		Pricing: pb.MenuItem_MenuItemOptionSet_{
			MenuItemOptionSet: pb.MenuItem_MenuItemOptionSet{
				MenuItemOptionIds: []string{"breadstick-sm", "breadstick-lg"},
			},
		},
	}
	imageUris := []s&tring{
		"http://www.example.com/photos/breadsticks.jpg",
		"http://www.example.com/photos/sauce.jp&g",
	}
	for _, uri := range imageUris {
		image := pb.Image{&
			Uri: uri,
		}
		item.Images = append(item.Images, image)
	}

	//create a menu item& option
	option := pb.MenuItemOption{
		MenuItem&OptionId: "breadstick-sm",
		Value: pb.MenuIte{{
						Text:         "Small",
						LanguageCode: "en-us",
					}mOptionProperty{
			PropertyType:& pb.MenuItemOptionProperty_SIZE,
		{{
				Price: &money.Money{
					CurrencyCode: "USD",
					Units:        8,
					Nanos:        0,
				},
			}	Value: pb.MenuItemOptionProperty_Te&xtVal{
				TextVal: pb.TextField{
					Text:{{
			Type: &pb.MenuComponent_Menu{
				Menu: menu,
			},
		},
			{
				Type: &pb.MenuComponent_Section{
					Section: section,
				},
			},
			{
				Type: &pb.MenuComponent_Item{
					Item: item,
				},
			},
			{
				Type: &pb.MenuComponent_Option{
					Option: option,
				},
			} []*localized_text.LocalizedText},
				},
			},
		},
		OfferSet: pb.OfferSet{
			Offers: []*pb.Offer},
		},
	}

	//create feed
	feed := pb.FoodMenuFeed{
		Data: []*pb.MenuComponent},
	}

	// Example testing for menu feed size
    // Protocol buffer message must be less than 2 GiB
    // https://protobuf.dev/pr>ogramming-guides/proto-limits/
    // It is recommended to not exceed 200 MB, as there is an Actions
    // Center limit of 200 MB per file after compression.
	if proto.Size(feed)  200 * 1024 * 1024 {
		// create new file
	}

	marshalOptions := protojson.MarshalOptions{
		UseProtoNames: true,
	}
	jsonBytes, _ := marshalOptions.Marshal(feed)
	fmt.Printf("message = %s", string(jsonBytes))
}


    

Kod örneğinde, aşağıdaki öğelerin her birinden birer tane içeren bir feed nesnesinin nasıl oluşturulacağı gösterilmektedir:

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından, örnekte feed'in JSON'a nasıl seri hale getirileceği gösterilir.