프로젝트 설정
- 새 프로젝트 디렉터리를 만듭니다.
- proto 정의에서 food_menu.protomoney.proto localized_text.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 출력 디렉터리 만들기: 생성됨
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 feedJSON = json.dumps(MessageToDict(feed, preserving_proto_field_name=True)) print(feedJSON)
코드 예에서는 다음 각 항목 중 하나를 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- MenuSection
- MenuItem
- MenuItemOption
그런 다음 피드를 JSON으로 직렬화하는 방법을 보여줍니다.
Python API를 사용하면 속성을 설정하여 중첩된 객체를 지연 초기화할 수 있습니다.TypeScript
-
TypeScript protoc 플러그인을 설치합니다.
npm init npm i -D typescript npm i ts-proto
ts-proto는 공식적으로 지원되는 Google 프로젝트가 아닙니다. - 출력 디렉터리를 만들고 클라이언트 소스 코드를 생성합니다.
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}] }; console.log(JSON.stringify(feed));
코드 예에서는 다음 각 항목 중 하나를 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- MenuSection
- MenuItem
- MenuItemOption
그런 다음 피드를 JSON으로 직렬화하는 방법을 보여줍니다.
자바
- 여기에 설명된 대로 maven 또는 gradle을 사용하여 protobuf-java 및 protobuf-java을 프로젝트에 추가합니다.
- 클라이언트 소스 코드 생성
protoc --java_out=src/main/java food_menu.proto money.proto localized_text.proto
Maven을 사용할 때 컴파일 시간에 protobuf-maven-plugin을 사용하여 소스 코드를 생성할 수 있습니다.
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 { 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); } }
코드 예에서는 다음 각 항목 중 하나를 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- 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" ) 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: ×tamppb.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)) }
코드 예에서는 다음 각 항목 중 하나를 사용하여 피드 객체를 만드는 방법을 보여줍니다.
- 메뉴
- MenuSection
- MenuItem
- MenuItemOption
그런 다음 피드를 JSON으로 직렬화하는 방법을 보여줍니다.