Menü feed'i oluşturma

Aşağıdaki eğitimde, Google Protocol Buffers (protobuf) tanımını kullanarak JSON'da nasıl feed oluşturulacağını göstereceğiz. Protobuf şemasına göre kaynak kod oluşturmak için protobuf derleyicisini kullanırız. Oluşturulan kaynak kodunu 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ı bölümünden yeni dosyalar olarak proje dizininizin köküne kopyalayın.
  • protoc derleyicisini yükleme

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

    Zip dosyasını açı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 kod oluşturma

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

    proto çıkış dizini oluşturulur: oluşturuldu

    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

Örnek projenin tamamını 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

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

    

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

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından örnekte, feed'in JSON olarak nasıl serileştirileceği gösterilmektedir.

Python API'si, özellikleri ayarlayarak iç içe yerleştirilmiş nesnelerin yavaş başlatılmasına olanak tanır.
  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ış dizini oluşturun ve istemci kaynak kodunu 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ırmaya alternatif olarak js_proto_library kuralını deneyin.

Kullanım örneği

Örnek projenin tamamını 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}]
};

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

  

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

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından örnekte, feed'in JSON olarak nasıl serileştirileceği gösterilmektedir.

  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 kodunu oluşturun.
    protoc --java_out=src/main/java food_menu.proto money.proto localized_text.proto
        

    Maven'i 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ırmaya alternatif olarak java_proto_library kuralını deneyin.

Kullanım örneği

Örnek projenin tamamını 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 {

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

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

    System.out.println(feedJSON);
  }
}

    

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

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından örnekte, feed'in JSON olarak nasıl serileştirileceği gösterilmektedir.

  1. Go için protoc eklentisini yükleme
    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 kodunu 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'u çalıştırmaya alternatif olarak go_proto_library kuralını deneyin.

Kullanım örneği

Örnek projenin tamamını 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"
)

func main() {

	//create a menu component
	menu := &pb.Menu{
		MenuId:      "menu1",
		MerchantIds: []string{"dining-1"},
		DisplayName: &pb.TextField{
			Text: []*localized_text.LocalizedText{{
				Text:         "Menu",
				LanguageCode: "en-us",
			}},
		},
		Language: "en-us",
		LastMerchantUpdateTime: &timestamppb.Timestamp{
			Seconds: 1633621547,
		},
	}

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

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

	//create a menu item option
	option := &pb.MenuItemOption{
		MenuItemOptionId: "breadstick-sm",
		Value: &pb.MenuItemOptionProperty{
			PropertyType: pb.MenuItemOptionProperty_SIZE,
			Value: &pb.MenuItemOptionProperty_TextVal{
				TextVal: &pb.TextField{
					Text: []*localized_text.LocalizedText{{
						Text:         "Small",
						LanguageCode: "en-us",
					}},
				},
			},
		},
		OfferSet: &pb.OfferSet{
			Offers: []*pb.Offer{{
				Price: &money.Money{
					CurrencyCode: "USD",
					Units:        8,
					Nanos:        0,
				},
			}},
		},
	}

	//create feed
	feed := &pb.FoodMenuFeed{
		Data: []*pb.MenuComponent{{
			Type: &pb.MenuComponent_Menu{
				Menu: menu,
			},
		},
			{
				Type: &pb.MenuComponent_Section{
					Section: section,
				},
			},
			{
				Type: &pb.MenuComponent_Item{
					Item: item,
				},
			},
			{
				Type: &pb.MenuComponent_Option{
					Option: option,
				},
			}},
	}

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


    

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

  • Menü
  • MenuSection
  • MenuItem
  • MenuItemOption

Ardından örnekte, feed'in JSON olarak nasıl serileştirileceği gösterilmektedir.