简体   繁体   中英

Import shared protobuf package into different protobuf packages

I'm designing some protobuf schemas for a project, what I want is to have independent packages, and a shared package. please see the example below.

// file: shared.proto
syntax = "proto3";
package package.shared;

message Address {
    string line = 1;
    string city = 2;
    string state = 3;
    string country = 4;
    uint32 zip = 5;
}

// file: invoice.proto
syntax = "proto3";
package package.invoice;

import "./shared.proto";

message Invoice {
    // some fields
    shared.Address address = 1;
}

// file: customer.proto
syntax = "proto3";
package package.customer;

import "./shared.proto";

message Customer {
    // some fields
    shared.Address address = 1;
}

I tried the above approach to design what I needed however, it's not working, getting the error Import Error: ./shared.proto is not found or has some error

Right now, I'm duplicating the shared fields with Invoice and Customer as a work around, I will be generating these protobuf 's for TypeScript and Java once complete.

If anyone knows a proper solution, please answer.

Note: This question is not a duplicate question, I tried to find import and shared package-related documents or answers, but still no luck.

Thanks

It is a little gnarly.

Think of protobuf packages like namespaces in your preferred programming language.

Generally, you want to reflect the package structure via the folder structure.

I tend to root my protos in a folder called protos . I'm using foo rather than package because package is a reserved name and could be problematic:

.
└── protos
    └── foo
        ├── invoice
        │   └── invoice.proto
        └── shared
            └── address.proto

The folder names should match the package (!) path ( foo.invoice , foo.shared ) while the file names generally reflect the message name.

invoice.proto :

syntax = "proto3";

package foo.invoice;

import "foo/shared/address.proto";

message Invoice {
    foo.shared.Address address = 1;
}

Invoice in package foo.invoice must reference Address by its fully-qualified package name foo.shared.Address .

address.proto :

syntax = "proto3";

package foo.shared;

message Address {
    string line = 1;
    string city = 2;
    string state = 3;
    string country = 4;
    uint32 zip = 5;
}

Then, using protoc :

protoc \
--proto_path=${PWD}/protos \
--java_out=${PWD} \
${PWD}/protos/foo/shared/address.proto \
${PWD}/protos/foo/invoice/invoice.proto

Because we've a single root ( ${PWD}/protos ) for the protos we're using, we can using a single --proto_path=${PWD}/protos to anchor the set.

It's necessary to fully specify the path (including the root) to each of the protos that we want to compile.

Produces:

.
├── foo
│   ├── invoice
│   │   └── InvoiceOuterClass.java
│   └── shared
│       └── AddressOuterClass.java
└── protos
    └── foo
        ├── invoice
        │   └── invoice.proto
        └── shared
            └── address.proto

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM