프로젝트 설정
- 새 프로젝트 디렉터리를 만듭니다.
- food_menu.proto money.proto localized_text.proto 콘텐츠를 proto 정의에서 새 파일로 프로젝트 디렉터리 루트에 복사합니다.
- protoc 컴파일러 설치
.proto 파일에서 소스 코드를 생성하려면 protoc 컴파일러가 필요합니다. 프로토콜 버퍼 GitHub 출시 페이지에서 최신 사전 빌드된 바이너리를 다운로드합니다.
zip을 추출하고 bin 경로를 PATH 환경 변수에 추가합니다. 예를 들면 다음과 같습니다.
unzip protoc-22.0-linux-x86_64.zip -d /usr/local/protoc export PATH="$PATH:/usr/local/protoc/bin"
소스 코드 생성
Python
- Python protobuf 라이브러리 설치
pip install protobuf
- 클라이언트 소스 코드를 생성합니다.
proto 출력 디렉터리 생성: generated
protoc --python_out=./generated food_menu.proto money.proto localized_text.proto
생성된 경로를 포함하도록 PYTHONPATH 환경 변수를 업데이트합니다. 예를 들면 다음과 같습니다.
export PYTHONPATH="$PYTHONPATH:./generated"
Bazel을 사용하는 경우 protoc을 실행하는 대신 py_proto_library 규칙을 사용해 보세요.
사용 예
전체 예시 프로젝트는 여기에서 확인할 수 있습니다.
"""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)
코드 예시에서는 다음 항목을 각각 하나씩 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- MenuSection
- MenuItem
- MenuItemOption
그런 다음 피드를 JSON으로 직렬화하는 방법을 보여줍니다.
Python API를 사용하면 속성을 설정하여 중첩된 객체를 지연 초기화할 수 있습니다.TypeScript
-
TypeScript protoc 플러그인을 설치합니다.
ts-proto 는 공식적으로 지원되는 Google 프로젝트가 아닙니다.npm init npm i -D typescript npm i ts-proto
- 출력 디렉터리를 만들고 클라이언트 소스 코드를 생성합니다.
proto 출력 디렉터리 생성: 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을 사용하는 경우 protoc을 실행하는 대신 js_proto_library 규칙을 사용해 보세요.
사용 예
전체 예시 프로젝트는 여기에서 확인할 수 있습니다.
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));
코드 예시에서는 다음 항목을 각각 하나씩 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- MenuSection
- MenuItem
- MenuItemOption
그런 다음 피드를 JSON으로 직렬화하는 방법을 보여줍니다.
자바
- 여기에 설명된 대로 Maven 또는 Gradle을 사용하여 종속 항목 protobuf-java 및 protobuf-java-util 을 프로젝트에 추가합니다.
- 클라이언트 소스 코드를 생성합니다.
protoc --java_out=src/main/java food_menu.proto money.proto localized_text.proto
protobuf-maven-plugin을 사용하여 Maven을 사용하는 경우 컴파일 시간에 소스 코드를 생성할 수 있습니다.
Bazel을 사용하는 경우 protoc을 실행하는 대신 java_proto_library 규칙을 사용해 보세요.
사용 예
전체 예시 프로젝트는 여기에서 확인할 수 있습니다.
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); } }
코드 예시에서는 다음 항목을 각각 하나씩 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- MenuSection
- MenuItem
- MenuItemOption
그런 다음 피드를 JSON으로 직렬화하는 방법을 보여줍니다.
Go
- Go용 protoc 플러그인을 설치합니다.
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
protoc-gen-go 플러그인을 포함하도록 PATH 환경 변수를 업데이트합니다. 예를 들면 다음과 같습니다.
export PATH="$PATH:$(go env GOPATH)/bin"
- 앱을 초기화하고 클라이언트 소스 코드를 생성합니다.
go mod init feed/app mkdir generated protoc --go_out=./generated/ food_menu.proto money.proto localized_text.proto
Bazel을 사용하는 경우 protoc을 실행하는 대신 go_proto_library 규칙을 사용해 보세요.
사용 예
전체 예시 프로젝트는 여기에서 확인할 수 있습니다.
/* 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)) }
코드 예시에서는 다음 항목을 각각 하나씩 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- MenuSection
- MenuItem
- MenuItemOption
그런 다음 피드를 JSON으로 직렬화하는 방법을 보여줍니다.