2010-10-27 33 views
6

Có thể phân tích cú pháp protobuf theo kiểu generic trong Java không?Phân tích cú pháp chung của PB trong java

Tôi đã xem xét GeneratedMessage và không thể tìm thấy cách phân tích cú pháp bất kỳ bộ đệm PB PB nào thành một GeneratedMessage.

Về cơ bản, tôi đang cố gắng phân tích cú pháp bộ đệm PB PB thành GeneratedMessage và sau đó tôi sẽ sử dụng phản chiếu để phát hiện các trường bên trong nó.

Trả lời

10

Trước hết, bạn không thể phân tích dữ liệu PB mà không biết lược đồ. Giản đồ ban đầu xuất phát từ tệp ".proto" và thường được nhúng trong mã được tạo bởi protoc. Tuy nhiên, bạn cũng có thể cho protoc để lưu trữ các lược đồ trong một định dạng đó là có thể sử dụng bởi các thư viện Java Protobuf:

protoc --descriptor_set_out=mymessages.desc mymessages.proto 

Sau đó tải nó trong mã Java của bạn:

FileInputStream fin = new FileInputStream("mymessages.desc"); 
Descriptors.FileDescriptorSet set = 
    Descriptors.FileDescriptorSet.parseFrom(fin); 
Descriptors.Descriptor md = set.getFile(0).getMessageType(0); 

Một khi bạn có schema cho nhắn (Descriptor.Descriptor) phân tích cú pháp nhắn rất dễ dàng:

byte[] data = ...; 
DynamicMessage m = DynamicMessage.parseFrom(md, data); 

DynamicMessage có một API phản chiếu cho phép bạn xem xét thông qua các lĩnh vực.

Phần lộn xộn đang kêu gọi công cụ protoc chuyển đổi tệp ".proto" thành định dạng có thể sử dụng. Thư viện C++ Protobuf có cách tải trực tiếp các tệp ".proto", nhưng không may là thư viện Java Protobuf không có.

2

Đây là ví dụ đúng:

private static DynamicMessage parseData(byte[] data) throws IOException, DescriptorValidationException { 
    FileInputStream fin = new FileInputStream("test.desc"); 
    DescriptorProtos.FileDescriptorSet set = DescriptorProtos.FileDescriptorSet.parseFrom(fin); 
    Descriptor md = Descriptors.FileDescriptor.buildFrom(set.getFile(0), new Descriptors.FileDescriptor[] {}).findMessageTypeByName("Person"); 
    return DynamicMessage.parseFrom(md, data); 
} 
+0

nếu bạn cần sử dụng findMessageTypeByName ("Người") không có nghĩa là bạn cần biết loại đối tượng trước khi phân tích cú pháp đó? –

3

Tôi đã giải pháp thử nghiệm với protobuf cuối cùng v.3.1.0

này giải pháp được nâng cấp lớn lên trên câu trả lời trước làm việc. Nhờ cả hai tác giả.

import com.example.address.AddressBookManager; 
import com.example.address.AddressBookProtos.AddressBook; 
import com.google.protobuf.DescriptorProtos.FileDescriptorSet; 
import com.google.protobuf.Descriptors; 
import com.google.protobuf.Descriptors.Descriptor; 
import com.google.protobuf.Descriptors.FileDescriptor; 
import com.google.protobuf.DynamicMessage; 

import java.io.File; 
import java.io.InputStream; 

public class DynamicMessageDemo { 

    private static final String ADDRESS_BOOK_SOURCE_FILENAME = "test.ab"; 
    private static final String ADDRESS_BOOK_DESC_FILENAME = 
     File.separator + "address.desc"; 

    public static void main(String[] args) throws Exception { 

     InputStream is = DynamicMessageDemo.class 
       .getResourceAsStream(ADDRESS_BOOK_DESC_FILENAME); 

     FileDescriptorSet set = FileDescriptorSet.parseFrom(is); 
     FileDescriptor fd = Descriptors.FileDescriptor.buildFrom(
       set.getFile(0), 
       new Descriptors.FileDescriptor[]{} 
       ); 

     // "AddressBook" is the second message in my *.proto 
     // so index must be '1' 
     Descriptor messageType = fd.getMessageTypes().get(1); 

     // for testing purpose 
     AddressBook book = AddressBookManager.readFromFile(ADDRESS_BOOK_SOURCE_FILENAME); 
     byte[] data = book.toByteArray(); 

     DynamicMessage message = DynamicMessage.parseFrom(messageType, data); 

     System.out.println("\n Dynamic message:\n" + message); 
    } 
} 
Các vấn đề liên quan