Thiết lập dự án
- Tạo một thư mục dự án mới.
- Sao chép nội dung của food_menu.proto money.proto localized_text.proto từ định nghĩa proto dưới dạng các tệp mới vào thư mục gốc của dự án.
- Cài đặt trình biên dịch protoc
Để tạo mã nguồn từ các tệp .proto, bạn sẽ cần trình biên dịch protoc. Tải tệp nhị phân được tạo sẵn mới nhất xuống từ trang phát hành của Protocol Buffers trên GitHub.
Giải nén tệp zip và thêm đường dẫn bin vào biến môi trường PATH, ví dụ:
unzip protoc-22.0-linux-x86_64.zip -d /usr/local/protoc export PATH="$PATH:/usr/local/protoc/bin"
Tạo mã nguồn
Python
- Cài đặt thư viện protobuf Python
pip install protobuf
- Tạo mã nguồn ứng dụng.
Tạo thư mục đầu ra proto: generated
protoc --python_out=./generated food_menu.proto money.proto localized_text.proto
Cập nhật biến môi trường PYTHONPATH để thêm đường dẫn đã tạo, ví dụ:
export PYTHONPATH="$PYTHONPATH:./generated"
Nếu bạn đang sử dụng Bazel, hãy thử quy tắc py_proto_library thay vì chạy protoc.
Ví dụ về cách sử dụng
Bạn có thể xem toàn bộ dự án mẫu tại đây.
"""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)
Ví dụ về mã minh hoạ cách tạo một đối tượng nguồn cấp dữ liệu với một đối tượng thuộc mỗi thực thể sau đây:
- Trình đơn
- MenuSection
- MenuItem
- MenuItemOption
Sau đó, ví dụ này cho thấy cách chuyển đổi nguồn cấp dữ liệu thành JSON.
API Python cho phép khởi tạo từng phần các đối tượng lồng nhau bằng cách thiết lập các thuộc tính.TypeScript
-
Cài đặt trình bổ trợ protoc TypeScript.
Xin lưu ý rằng ts-proto không phải là một dự án chính thức được Google hỗ trợ.npm init npm i -D typescript npm i ts-proto
- Tạo thư mục đầu ra và tạo mã nguồn ứng dụng.
Tạo thư mục đầu ra 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
Nếu bạn đang sử dụng Bazel, hãy thử quy tắc js_proto_library thay vì chạy protoc.
Ví dụ về cách sử dụng
Bạn có thể xem toàn bộ dự án mẫu tại đây.
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));
Ví dụ về mã minh hoạ cách tạo một đối tượng nguồn cấp dữ liệu với một đối tượng thuộc mỗi thực thể sau đây:
- Trình đơn
- MenuSection
- MenuItem
- MenuItemOption
Sau đó, ví dụ này cho thấy cách chuyển đổi nguồn cấp dữ liệu thành JSON.
Java
- Thêm các phần phụ thuộc protobuf-java và protobuf-java-util vào dự án bằng maven hoặc gradle như mô tả tại đây.
- Tạo mã nguồn ứng dụng.
protoc --java_out=src/main/java food_menu.proto money.proto localized_text.proto
Bạn có thể dùng protobuf-maven-plugin để tạo mã nguồn trong thời gian biên dịch khi dùng maven.
Nếu bạn đang sử dụng Bazel, hãy thử quy tắc java_proto_library thay vì chạy protoc.
Ví dụ về cách sử dụng
Bạn có thể xem toàn bộ dự án mẫu tại đây.
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); } }
Ví dụ về mã minh hoạ cách tạo một đối tượng nguồn cấp dữ liệu với một đối tượng thuộc mỗi thực thể sau đây:
- Trình đơn
- MenuSection
- MenuItem
- MenuItemOption
Sau đó, ví dụ này cho thấy cách chuyển đổi nguồn cấp dữ liệu thành JSON.
Go
- Cài đặt trình bổ trợ protoc cho Go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
Cập nhật biến môi trường PATH để thêm trình bổ trợ protoc-gen-go, ví dụ:
export PATH="$PATH:$(go env GOPATH)/bin"
- Khởi chạy ứng dụng và tạo mã nguồn ứng dụng.
go mod init feed/app mkdir generated protoc --go_out=./generated/ food_menu.proto money.proto localized_text.proto
Nếu bạn đang sử dụng Bazel, hãy thử quy tắc go_proto_library thay vì chạy protoc.
Ví dụ về cách sử dụng
Bạn có thể xem toàn bộ dự án mẫu tại đây.
/* 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)) }
Ví dụ về mã minh hoạ cách tạo một đối tượng nguồn cấp dữ liệu với một đối tượng thuộc mỗi thực thể sau đây:
- Trình đơn
- MenuSection
- MenuItem
- MenuItemOption
Sau đó, ví dụ này cho thấy cách chuyển đổi nguồn cấp dữ liệu thành JSON.