প্রোটোবুফ 3 এ কীভাবে anচ্ছিক ক্ষেত্রটি সংজ্ঞায়িত করা যায়


104

প্রোটোবুফে (প্রোটো 3 সিনট্যাক্স) Iচ্ছিক ক্ষেত্র সহ আমাকে একটি বার্তা নির্দিষ্ট করতে হবে। প্রোটো 2 সিনট্যাক্সের ক্ষেত্রে, আমি যে বার্তাটি প্রকাশ করতে চাই তা হ'ল কিছু:

message Foo {
    required int32 bar = 1;
    optional int32 baz = 2;
}

আমার বোঝাপড়া থেকে "alচ্ছিক" ধারণাটি সিনট্যাক্স প্রোটো 3 থেকে সরানো হয়েছে (প্রয়োজনীয় ধারণার পাশাপাশি)। যদিও এটি বিকল্পটি পরিষ্কার নয় - প্রেরকের কাছ থেকে কোনও ক্ষেত্র নির্দিষ্ট করা হয়নি তা নির্ধারণের জন্য ডিফল্ট মানটি ব্যবহার করে, যদি একটি ডিফল্ট মান বৈধ মান ডোমেনের অন্তর্ভুক্ত থাকে তবে একটি অস্পষ্টতা ছেড়ে যায় (উদাহরণস্বরূপ বুলিয়ান টাইপ বিবেচনা করুন)।

সুতরাং, আমি কীভাবে উপরে বার্তাটি এনকোড করব? ধন্যবাদ.


একটি সমাধান সমাধান নীচের পদ্ধতির? বার্তা NoBaz {} বার্তা Foo {int32 বার = 1; oneof baz {NoBaz undefined = 2; int32 সংজ্ঞায়িত = 3; }; }
ম্যাক্সপ

4
আছে এই প্রশ্নের একটি প্রোটো 2 সংস্করণ , যদি জন এই এটি কিন্তু প্রোটো 2. ব্যবহার করছেন
chwarr

4
প্রোটো 3 মূলত সমস্ত ক্ষেত্রকে alচ্ছিক করে তোলে। তবে স্কেলারের ক্ষেত্রে তারা "ফিল্ড সেট না করা" এবং "ফিল্ড সেট কিন্তু ডিফল্ট মান হিসাবে" পার্থক্য করা অসম্ভব করে তুলেছে। যদি আপনি আপনার স্কেলারটি একক এককতে মুড়ে রাখেন যেমন - বার্তা ব্লাহ {oneof v1 {int32 foo = 1; }}, তারপরে আপনি foo আসলে সেট হয়েছিল কিনা তা আবার পরীক্ষা করতে পারেন। পাইথনের পক্ষে কমপক্ষে আপনি সরাসরি foo এ পরিচালনা করতে পারেন যেন এটি কোনও একের মধ্যে না থাকে এবং আপনি হাসফিল্ড ("foo") জিজ্ঞাসা করতে পারেন।
jschultz410

4
@MaxP হতে পারে আপনি এ গৃহীত উত্তর পরিবর্তন হতে পারে stackoverflow.com/a/62566052/66465 এখন protobuf 3 এর নতুন সংস্করণ থেকেইoptional
SebastianK

উত্তর:


40

Protobuf যেহেতু মুক্তি 3,12 , proto3 ব্যবহার সমর্থন করে optionalশব্দ (ঠিক proto2 হিসেবে) একটি স্কেলার ক্ষেত্র উপস্থিতি তথ্য দিতে।

syntax = "proto3";

message Foo {
    int32 bar = 1;
    optional int32 baz = 2;
}

উপরের ক্ষেত্রের জন্য এ has_baz()/ hasBaz()পদ্ধতিটি উত্পন্ন হয় optionalঠিক যেমনটি প্রোটো 2 তে ছিল।

হুডের নীচে, প্রোটোকটি কোনও optionalক্ষেত্রকে কার্যকরভাবে আচরণ করে যেমন এটি একটি oneofমোড়ক ব্যবহার করে ঘোষিত হয়েছিল , যেমন সাইবারসনোপির উত্তর থেকে বোঝা যাচ্ছে:

message Foo {
    int32 bar = 1;
    oneof optional_baz {
        int32 baz = 2;
    }
}

যদি আপনি ইতিমধ্যে এই পদ্ধতিটি ব্যবহার করেছেন, আপনি তার বার্তা ঘোষণাগুলি (থেকে স্যুইচ oneofকরুন optional) পরিষ্কার করতে পারেন , যেহেতু তারের ফর্ম্যাটটি একই।

আপনি অ্যাপ্লিকেশন নোটে ক্ষেত্রের উপস্থিতি এবং optionalপ্রোটো 3-তে নিট -কৌতুকপূর্ণ বিবরণ খুঁজে পেতে পারেন : ফিল্ড উপস্থিতি ডক।

3.12 প্রকাশে, এই কার্যকারিতাটির জন্য --experimental_allow_proto3_optionalপতাকাটি প্রোটকে প্রেরণ করা প্রয়োজন । বৈশিষ্ট্য ঘোষণা বলছেন এটি "আশা সাধারণভাবে উপলভ্য 3.13 মধ্যে" হতে হবে।

অক্টোবর 2020 আপডেট: বৈশিষ্ট্যটি এখনও 3.13 রিলিজে পরীক্ষামূলক (পতাকা প্রয়োজন) হিসাবে বিবেচিত হয় ।


4
আপনি কীভাবে সি # তে পতাকা পাস করবেন তা জানেন?
জেমস হ্যানকক

প্রোটো 3 আরও ভাল সিনট্যাক্স যুক্ত করেছে এটি এখন সেরা উত্তর। দুর্দান্ত কলআউট জারাড!
ইভান মুরান

কেবলমাত্র যুক্ত করতে optional int xyz: 1) has_xyzalচ্ছিক মান 2 সেট করা ছিল কিনা তা সনাক্ত করে ) মানটি clear_xyzআনসেট করবে will এখানে আরও তথ্য: github.com/protocolbuffers/protobuf/blob/master/docs/…
ইভান মোরান

@ জামেসহানকক বা জাভা?
টবি আকিনিয়েমি

@ তোবিআকিনেমি ??
জেমস হ্যানকক

123

প্রোটো 3-তে, সমস্ত ক্ষেত্রগুলি "alচ্ছিক" (যাতে প্রেরক সেগুলি সেট করতে ব্যর্থ হয় তবে এটি ত্রুটি নয়)। তবে, ক্ষেত্রগুলি আর "অবিচ্ছেদ্য" নয়, কোনও ক্ষেত্রের মধ্যে তার ডিফল্ট মান হিসাবে বনাম কোনও স্থানে সেট করা হয়নি তা স্পষ্ট করে সেট করার কোনও উপায় নেই।

আপনার যদি কোনও "নাল" রাষ্ট্রের প্রয়োজন হয় (এবং এর জন্য আপনি ব্যবহার করতে পারেন এমন কোনও সীমার মান নেই) তবে এর পরিবর্তে আপনাকে এটিকে আলাদা ক্ষেত্র হিসাবে এনকোড করতে হবে। উদাহরণস্বরূপ, আপনি এটি করতে পারেন:

message Foo {
  bool has_baz = 1;  // always set this to "true" when using baz
  int32 baz = 2;
}

বিকল্পভাবে, আপনি ব্যবহার করতে পারেন oneof:

message Foo {
  oneof baz {
    bool baz_null = 1;  // always set this to "true" when null
    int32 baz_value = 2;
  }
}

oneofসংস্করণ আরো স্পষ্ট এবং তারের উপর আরও দক্ষ কিন্তু বুঝতে কিভাবে প্রয়োজন oneofমান কাজ করি।

পরিশেষে, আরেকটি নিখুঁত যুক্তিসঙ্গত বিকল্প হ'ল প্রোটো 2 দিয়ে থাকা। প্রোটো 2 হ্রাস করা হয় না এবং প্রকৃতপক্ষে অনেকগুলি প্রকল্প (গুগলের অভ্যন্তরে অন্তর্ভুক্ত) প্রোটো 2 বৈশিষ্ট্যগুলির উপর নির্ভর করে যা প্রোটো 3-এ সরানো হয়, তাই সম্ভবত তারা কখনও স্যুইচ করবে না। সুতরাং, অদূর ভবিষ্যতের জন্য এটি ব্যবহার করা নিরাপদ।


আপনার সমাধানের অনুরূপ, আমার মন্তব্যে, আমি একটিকে আসল মান এবং নাল টাইপের (একটি খালি বার্তা) ব্যবহার করার প্রস্তাব করেছি। এইভাবে আপনি বুলিয়ান মান নিয়ে বিরক্ত করবেন না (যা প্রাসঙ্গিক হওয়া উচিত নয়, কারণ যদি বুলিয়ান থাকে তবে কোনও বাজ_ভ্যালু নেই) সঠিক?
ম্যাক্সপ

4
@ ম্যাক্সপি আপনার সমাধানটি কাজ করে তবে আমি একটি খালি বার্তায় একটি বুলিয়ান প্রস্তাব করব। হয় তারে দুটি বাইট লাগবে তবে খালি বার্তাটি হ্যান্ডেল করতে যথেষ্ট বেশি সিপিইউ, র‌্যাম এবং জেনারেটেড কোড ব্লাট নেবে।
কেন্টন ভারদা

13
আমি ফু {oneof baz {int32 বাজ_ভ্যালু = 1 বার্তাটি পেয়েছি; pretty pretty বেশ ভাল কাজ করে।
সাইবারস্নপি

@ সাইবারস্নুপি আপনি কি উত্তর হিসাবে পোস্ট করতে পারেন? আপনার সমাধান নিখুঁত এবং মার্জিত কাজ করে।
চেং চেন

@ সাইবারসনোপি এই জাতীয় কাঠামোর মতো প্রতিক্রিয়া বার্তা প্রেরণ করার সময় আপনি কি কোনও সমস্যার মুখোমুখি হয়েছিলেন: বার্তা ফুওলিস্ট - বারবার ফু ফুস = 1; ? আপনার সমাধানটি দুর্দান্ত তবে আমি এখন সার্ভারের প্রতিক্রিয়া হিসাবে ফুললিস্ট প্রেরণে সমস্যায় পড়ছি।
ক্যাফিনেটেফটেন

95

একটি উপায় হ'ল oneofগৃহীত উত্তরে প্রস্তাবিত মত ব্যবহার করা ।

আর একটি হ'ল মোড়কের জিনিস ব্যবহার করা। গুগল ইতিমধ্যে এগুলি সরবরাহ করে বলে আপনাকে সেগুলি নিজের লেখার দরকার নেই:

আপনার .Prooto ফাইলের শীর্ষে এই আমদানিটি যুক্ত করুন:

import "google/protobuf/wrappers.proto";

এখন আপনি প্রতিটি সাধারণ ধরণের জন্য বিশেষ মোড়ক ব্যবহার করতে পারেন:

DoubleValue
FloatValue
Int64Value
UInt64Value
Int32Value
UInt32Value
BoolValue
StringValue
BytesValue

সুতরাং মূল প্রশ্নের উত্তর দেওয়ার জন্য এই জাতীয় একটি মোড়কের ব্যবহার এরকম হতে পারে:

message Foo {
    int32 bar = 1;
    google.protobuf.Int32Value baz = 2;
}

এখন জাভাতে উদাহরণস্বরূপ আমি স্টাফগুলি করতে পারি:

if(foo.hasBaz()) { ... }


4
কিভাবে কাজ করে? যখন baz=nullআর যখন bazপাশ করা হয় না, উভয় ক্ষেত্রেই hasBaz()বলছেন false!
mayankcpdixit

ধারণাটি সহজ: আপনি মোড়কের জিনিসগুলি বা অন্য কথায় ব্যবহারকারীর সংজ্ঞায়িত প্রকারগুলি ব্যবহার করেন। এই মোড়কযুক্ত জিনিসগুলি অনুপস্থিত অনুমোদিত। জিআরপিসি নিয়ে কাজ করার সময় আমি যে জাভা উদাহরণটি দিয়েছি তা আমার পক্ষে ভাল কাজ করেছে।
ভিএম 4

হ্যাঁ! আমি সাধারণ ধারণাটি বুঝতে পারি, তবে আমি এটি কার্যকরভাবে দেখতে চেয়েছিলাম। আমি যা বুঝতে পারি না তা হ'ল: (এমনকি মোড়কের
বস্তুতেও

4
এই পথেই যেতে হবে। সি # দিয়ে, উত্পন্ন কোডটি নুলযোগ্য <টি> বৈশিষ্ট্য তৈরি করে।
অ্যারন হুডন

4
আসল আউশনারের চেয়ে ভাল!
দেব আগরওয়াল

32

কেন্টনের উত্তরের উপর ভিত্তি করে, একটি সহজ কিন্তু কার্যক্ষম সমাধানটি দেখে মনে হচ্ছে:

message Foo {
    oneof optional_baz { // "optional_" prefix here just serves as an indicator, not keyword in proto2
        int32 baz = 1;
    }
}

এটি কীভাবে alচ্ছিক-চরিত্রকে মূর্ত করে?
জেএফএফআইজিজি

19
মূলত, একের নাম খারাপ হয়। এর অর্থ "সর্বাধিক এক" একটি সম্ভাব্য নাল মান সর্বদা আছে।
ect3ctic

যদি সেট না করে ফেলে রাখা হয় তবে মান Noneকেসটি হবে (সি # তে) - আপনার পছন্দের ভাষার জন্য এনাম-টাইপ দেখুন।
নিটজেল

হ্যাঁ, প্রোটো 3-তে এই বিড়ালটিকে ত্বকের সবচেয়ে ভাল উপায় - এমনকি যদি ছবিটি কিছুটা কুৎসিত করে তোলে।
jschultz410

যাইহোক, এটি কিছুটা বোঝায় যে আপনি কোনও ক্ষেত্রের অনুপস্থিতিকে স্পষ্টভাবে নাল মান হিসাবে সেট করে ব্যাখ্যা করতে পারেন। অন্য কথায়, 'fieldচ্ছিক ক্ষেত্র নির্দিষ্ট করা হয়নি' এবং 'ক্ষেত্রটি ইচ্ছুকভাবে নির্দিষ্ট করা হয়নি এটি অর্থ নাল' বলে বোঝানোর মধ্যে কিছু অস্পষ্টতা রয়েছে। যদি আপনি সেই স্তরের যথাযথতা সম্পর্কে যত্নশীল হন তবে আপনি একটিতে অতিরিক্ত google.protobuf.NullValue ক্ষেত্র যোগ করতে পারেন যা আপনাকে 'ক্ষেত্র নির্দিষ্ট না করা', 'ক্ষেত্রের মান X হিসাবে নির্দিষ্ট করা' এবং 'নাল হিসাবে নির্দিষ্ট ক্ষেত্রের' মধ্যে পার্থক্য করতে দেয় । এটি ধোঁয়াটে ধরণের, তবে এর কারণ প্রোটো 3 জাসন যেমন সরাসরি নাল সমর্থন করে না।
jschultz410

7

@ সাইবারসনোপি'র পরামর্শটি প্রসারিত করতে এখানে

যদি আপনার কাছে এমন একটি বার্তার সাথে একটি। ফটো ফাইল থাকে:

message Request {
    oneof option {
        int64 option_value = 1;
    }
}

আপনি প্রদত্ত কেস বিকল্পগুলি (জাভা উত্পন্ন কোড) ব্যবহার করতে পারেন :

সুতরাং আমরা এখন নিম্নলিখিত হিসাবে কিছু কোড লিখতে পারেন:

Request.OptionCase optionCase = request.getOptionCase();
OptionCase optionNotSet = OPTION_NOT_SET;

if (optionNotSet.equals(optionCase)){
    // value not set
} else {
    // value set
}

পাইথনে এটি আরও সহজ। আপনি কেবল অনুরোধ করতে পারেন asহ্যাসফিল্ড ("বিকল্প_মূল্য")। এছাড়াও, আপনার বার্তায় যদি এরকম একগুচ্ছ সিঙ্গেলটন থাকে তবে আপনি কেবলমাত্র সাধারণ স্কেলারের মতোই তাদের থাকা স্কেলারগুলি অ্যাক্সেস করতে পারেন।
jschultz410

1

এটি সম্পর্কে একটি ভাল পোস্ট রয়েছে: https://itnext.io/protobuf-and-null-support-1908a15311b6

সমাধানটি আপনার আসল ব্যবহারের ক্ষেত্রে নির্ভর করে:


LInk এর জন্য ধন্যবাদ: itnext.io/protobuf-and-null-support-1908a15311b6 সত্যিই দরকারী।
অভিলাষ_গোয়াল

-1

আরেকটি উপায় হ'ল আপনি প্রতিটি alচ্ছিক ক্ষেত্রে বিটমাস্ক ব্যবহার করতে পারেন। এবং মানগুলি সেট করা থাকলে সেই বিটগুলি সেট করুন এবং মানগুলি সেট না করা সেই বিটগুলি পুনরায় সেট করুন

enum bitsV {
    baz_present = 1; // 0x01
    baz1_present = 2; // 0x02

}
message Foo {
    uint32 bitMask;
    required int32 bar = 1;
    optional int32 baz = 2;
    optional int32 baz1 = 3;
}

বিটমাস্কের মানটি পরীক্ষা করার জন্য ing

if (bitMask & baz_present)
    baz is present

if (bitMask & baz1_present)
    baz1 is present

-2

আপনি যদি ডিফল্ট উদাহরণের সাথে রেফারেন্সগুলি তুলনা করে সূচনা করা শুরু করতে পারেন:

GRPCContainer container = myGrpcResponseBean.getContainer();
if (container.getDefaultInstanceForType() != container) {
...
}

4
এটি একটি ভাল সাধারণ পদ্ধতি নয় কারণ খুব প্রায়ই ক্ষেত্রের জন্য ডিফল্ট মান হ'ল পুরোপুরি গ্রহণযোগ্য মান এবং সেই পরিস্থিতিতে আপনি "ক্ষেত্রের অনুপস্থিত" এবং "ফিল্ড উপস্থিত না থাকলেও ডিফল্ট হিসাবে সেট" থাকেন between
jschultz410
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.