Protobuf map type JSON format uses string literal “key” and “value” not the actual values





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I am trying to convert a protobuf object to JSON format using com.googlecode.protobuf.format.JsonFormat but the map type came out unexpected.



My message is like this



message Response {
repeated Candidate candidates = 1;
map<string, ErrorMessage> errors = 2;
}

message ErrorMessage {
string message = 0;
ErrorType type = 1;
}

enum ErrorType {
ERROR = 0;
WARNING = 1;
}


The issue is the JSON format of the Response object I created



Response response = ...
Return new ResponseEntity<>(new JsonFormat().printToString(response), HttpStatus.OK);


I expect the errors be formatted as a map keyed by the string value (of the map key)



...
"errors": {
"someID" : {
"message": "blah blah",
"type": "ERROR"
}
}


However the actual output is (I evaluated only the new JsonFormat().printToString(response) part in intellij)



...
"errors": {
"key": "someID",
"value": {
"message": "blah blah",
"type": "ERROR"
}
}


I hope it's some small configuration I missed to make protobuf (or Jackson?) to be aware of the actual key value ? not using "key" and "value".



BTW, what's the point of having literal "key" and "value" field in a map type ? You can't do constituent lookup with it and you might just use a custom type/object.










share|improve this question





























    1















    I am trying to convert a protobuf object to JSON format using com.googlecode.protobuf.format.JsonFormat but the map type came out unexpected.



    My message is like this



    message Response {
    repeated Candidate candidates = 1;
    map<string, ErrorMessage> errors = 2;
    }

    message ErrorMessage {
    string message = 0;
    ErrorType type = 1;
    }

    enum ErrorType {
    ERROR = 0;
    WARNING = 1;
    }


    The issue is the JSON format of the Response object I created



    Response response = ...
    Return new ResponseEntity<>(new JsonFormat().printToString(response), HttpStatus.OK);


    I expect the errors be formatted as a map keyed by the string value (of the map key)



    ...
    "errors": {
    "someID" : {
    "message": "blah blah",
    "type": "ERROR"
    }
    }


    However the actual output is (I evaluated only the new JsonFormat().printToString(response) part in intellij)



    ...
    "errors": {
    "key": "someID",
    "value": {
    "message": "blah blah",
    "type": "ERROR"
    }
    }


    I hope it's some small configuration I missed to make protobuf (or Jackson?) to be aware of the actual key value ? not using "key" and "value".



    BTW, what's the point of having literal "key" and "value" field in a map type ? You can't do constituent lookup with it and you might just use a custom type/object.










    share|improve this question

























      1












      1








      1








      I am trying to convert a protobuf object to JSON format using com.googlecode.protobuf.format.JsonFormat but the map type came out unexpected.



      My message is like this



      message Response {
      repeated Candidate candidates = 1;
      map<string, ErrorMessage> errors = 2;
      }

      message ErrorMessage {
      string message = 0;
      ErrorType type = 1;
      }

      enum ErrorType {
      ERROR = 0;
      WARNING = 1;
      }


      The issue is the JSON format of the Response object I created



      Response response = ...
      Return new ResponseEntity<>(new JsonFormat().printToString(response), HttpStatus.OK);


      I expect the errors be formatted as a map keyed by the string value (of the map key)



      ...
      "errors": {
      "someID" : {
      "message": "blah blah",
      "type": "ERROR"
      }
      }


      However the actual output is (I evaluated only the new JsonFormat().printToString(response) part in intellij)



      ...
      "errors": {
      "key": "someID",
      "value": {
      "message": "blah blah",
      "type": "ERROR"
      }
      }


      I hope it's some small configuration I missed to make protobuf (or Jackson?) to be aware of the actual key value ? not using "key" and "value".



      BTW, what's the point of having literal "key" and "value" field in a map type ? You can't do constituent lookup with it and you might just use a custom type/object.










      share|improve this question














      I am trying to convert a protobuf object to JSON format using com.googlecode.protobuf.format.JsonFormat but the map type came out unexpected.



      My message is like this



      message Response {
      repeated Candidate candidates = 1;
      map<string, ErrorMessage> errors = 2;
      }

      message ErrorMessage {
      string message = 0;
      ErrorType type = 1;
      }

      enum ErrorType {
      ERROR = 0;
      WARNING = 1;
      }


      The issue is the JSON format of the Response object I created



      Response response = ...
      Return new ResponseEntity<>(new JsonFormat().printToString(response), HttpStatus.OK);


      I expect the errors be formatted as a map keyed by the string value (of the map key)



      ...
      "errors": {
      "someID" : {
      "message": "blah blah",
      "type": "ERROR"
      }
      }


      However the actual output is (I evaluated only the new JsonFormat().printToString(response) part in intellij)



      ...
      "errors": {
      "key": "someID",
      "value": {
      "message": "blah blah",
      "type": "ERROR"
      }
      }


      I hope it's some small configuration I missed to make protobuf (or Jackson?) to be aware of the actual key value ? not using "key" and "value".



      BTW, what's the point of having literal "key" and "value" field in a map type ? You can't do constituent lookup with it and you might just use a custom type/object.







      java json serialization protocol-buffers protobuf-java






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 16 '18 at 11:45









      CrazyGreenHandCrazyGreenHand

      1161415




      1161415
























          1 Answer
          1






          active

          oldest

          votes


















          1














          This code works perfectly for me:



          test.proto



          syntax = "proto2";
          package by.dev.madhead;
          option java_outer_classname = "SO";

          message Candidate {

          }

          enum ErrorType {
          ERROR = 0;
          WARNING = 1;
          }

          message ErrorMessage {
          required string message = 1;
          required ErrorType type = 2;
          }

          message Response {
          repeated Candidate candidates = 1;
          map<string, ErrorMessage> errors = 2;
          }


          App.java



          public class App {
          public static void main(String args) throws InvalidProtocolBufferException {
          SO.Response response = SO.Response.newBuilder()
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .putErrors("error1", SO.ErrorMessage.newBuilder().setMessage("error1").setType(SO.ErrorType.ERROR).build())
          .putErrors("error2", SO.ErrorMessage.newBuilder().setMessage("error2").setType(SO.ErrorType.WARNING).build())
          .build();

          System.out.println(JsonFormat.printer().print(response));
          }
          }


          The output is:



          {
          "candidates": [{
          }, {
          }, {
          }],
          "errors": {
          "error1": {
          "message": "error1",
          "type": "ERROR"
          },
          "error2": {
          "message": "error2",
          "type": "WARNING"
          }
          }
          }


          Which has no keys and value as you see. Make sure that you printed not the message itself, but the result of JsonFormat.printer().print(). Basically, key and values you've seen are from internal toString() implementation of Protobuf Message.



          And the full class name for JsonFormat is com.google.protobuf.util.JsonFormat, not com.googlecode.protobuf.format.JsonFormat.






          share|improve this answer
























          • Thank you for your help ! Indeed I used com.googlecode.protobuf.format.JsonFormat instead of com.google.protobuf.util.JsonFormat which was the issue. The googlecode one seems to be an out of date formatting util ?

            – CrazyGreenHand
            Nov 16 '18 at 16:50













          • I guess, yes, it's outdated. All Google results refer to com.google.protobuf.util.JsonFormat.

            – madhead
            Nov 16 '18 at 17:17












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337220%2fprotobuf-map-type-json-format-uses-string-literal-key-and-value-not-the-actu%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          This code works perfectly for me:



          test.proto



          syntax = "proto2";
          package by.dev.madhead;
          option java_outer_classname = "SO";

          message Candidate {

          }

          enum ErrorType {
          ERROR = 0;
          WARNING = 1;
          }

          message ErrorMessage {
          required string message = 1;
          required ErrorType type = 2;
          }

          message Response {
          repeated Candidate candidates = 1;
          map<string, ErrorMessage> errors = 2;
          }


          App.java



          public class App {
          public static void main(String args) throws InvalidProtocolBufferException {
          SO.Response response = SO.Response.newBuilder()
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .putErrors("error1", SO.ErrorMessage.newBuilder().setMessage("error1").setType(SO.ErrorType.ERROR).build())
          .putErrors("error2", SO.ErrorMessage.newBuilder().setMessage("error2").setType(SO.ErrorType.WARNING).build())
          .build();

          System.out.println(JsonFormat.printer().print(response));
          }
          }


          The output is:



          {
          "candidates": [{
          }, {
          }, {
          }],
          "errors": {
          "error1": {
          "message": "error1",
          "type": "ERROR"
          },
          "error2": {
          "message": "error2",
          "type": "WARNING"
          }
          }
          }


          Which has no keys and value as you see. Make sure that you printed not the message itself, but the result of JsonFormat.printer().print(). Basically, key and values you've seen are from internal toString() implementation of Protobuf Message.



          And the full class name for JsonFormat is com.google.protobuf.util.JsonFormat, not com.googlecode.protobuf.format.JsonFormat.






          share|improve this answer
























          • Thank you for your help ! Indeed I used com.googlecode.protobuf.format.JsonFormat instead of com.google.protobuf.util.JsonFormat which was the issue. The googlecode one seems to be an out of date formatting util ?

            – CrazyGreenHand
            Nov 16 '18 at 16:50













          • I guess, yes, it's outdated. All Google results refer to com.google.protobuf.util.JsonFormat.

            – madhead
            Nov 16 '18 at 17:17
















          1














          This code works perfectly for me:



          test.proto



          syntax = "proto2";
          package by.dev.madhead;
          option java_outer_classname = "SO";

          message Candidate {

          }

          enum ErrorType {
          ERROR = 0;
          WARNING = 1;
          }

          message ErrorMessage {
          required string message = 1;
          required ErrorType type = 2;
          }

          message Response {
          repeated Candidate candidates = 1;
          map<string, ErrorMessage> errors = 2;
          }


          App.java



          public class App {
          public static void main(String args) throws InvalidProtocolBufferException {
          SO.Response response = SO.Response.newBuilder()
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .putErrors("error1", SO.ErrorMessage.newBuilder().setMessage("error1").setType(SO.ErrorType.ERROR).build())
          .putErrors("error2", SO.ErrorMessage.newBuilder().setMessage("error2").setType(SO.ErrorType.WARNING).build())
          .build();

          System.out.println(JsonFormat.printer().print(response));
          }
          }


          The output is:



          {
          "candidates": [{
          }, {
          }, {
          }],
          "errors": {
          "error1": {
          "message": "error1",
          "type": "ERROR"
          },
          "error2": {
          "message": "error2",
          "type": "WARNING"
          }
          }
          }


          Which has no keys and value as you see. Make sure that you printed not the message itself, but the result of JsonFormat.printer().print(). Basically, key and values you've seen are from internal toString() implementation of Protobuf Message.



          And the full class name for JsonFormat is com.google.protobuf.util.JsonFormat, not com.googlecode.protobuf.format.JsonFormat.






          share|improve this answer
























          • Thank you for your help ! Indeed I used com.googlecode.protobuf.format.JsonFormat instead of com.google.protobuf.util.JsonFormat which was the issue. The googlecode one seems to be an out of date formatting util ?

            – CrazyGreenHand
            Nov 16 '18 at 16:50













          • I guess, yes, it's outdated. All Google results refer to com.google.protobuf.util.JsonFormat.

            – madhead
            Nov 16 '18 at 17:17














          1












          1








          1







          This code works perfectly for me:



          test.proto



          syntax = "proto2";
          package by.dev.madhead;
          option java_outer_classname = "SO";

          message Candidate {

          }

          enum ErrorType {
          ERROR = 0;
          WARNING = 1;
          }

          message ErrorMessage {
          required string message = 1;
          required ErrorType type = 2;
          }

          message Response {
          repeated Candidate candidates = 1;
          map<string, ErrorMessage> errors = 2;
          }


          App.java



          public class App {
          public static void main(String args) throws InvalidProtocolBufferException {
          SO.Response response = SO.Response.newBuilder()
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .putErrors("error1", SO.ErrorMessage.newBuilder().setMessage("error1").setType(SO.ErrorType.ERROR).build())
          .putErrors("error2", SO.ErrorMessage.newBuilder().setMessage("error2").setType(SO.ErrorType.WARNING).build())
          .build();

          System.out.println(JsonFormat.printer().print(response));
          }
          }


          The output is:



          {
          "candidates": [{
          }, {
          }, {
          }],
          "errors": {
          "error1": {
          "message": "error1",
          "type": "ERROR"
          },
          "error2": {
          "message": "error2",
          "type": "WARNING"
          }
          }
          }


          Which has no keys and value as you see. Make sure that you printed not the message itself, but the result of JsonFormat.printer().print(). Basically, key and values you've seen are from internal toString() implementation of Protobuf Message.



          And the full class name for JsonFormat is com.google.protobuf.util.JsonFormat, not com.googlecode.protobuf.format.JsonFormat.






          share|improve this answer













          This code works perfectly for me:



          test.proto



          syntax = "proto2";
          package by.dev.madhead;
          option java_outer_classname = "SO";

          message Candidate {

          }

          enum ErrorType {
          ERROR = 0;
          WARNING = 1;
          }

          message ErrorMessage {
          required string message = 1;
          required ErrorType type = 2;
          }

          message Response {
          repeated Candidate candidates = 1;
          map<string, ErrorMessage> errors = 2;
          }


          App.java



          public class App {
          public static void main(String args) throws InvalidProtocolBufferException {
          SO.Response response = SO.Response.newBuilder()
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .addCandidates(SO.Candidate.newBuilder().build())
          .putErrors("error1", SO.ErrorMessage.newBuilder().setMessage("error1").setType(SO.ErrorType.ERROR).build())
          .putErrors("error2", SO.ErrorMessage.newBuilder().setMessage("error2").setType(SO.ErrorType.WARNING).build())
          .build();

          System.out.println(JsonFormat.printer().print(response));
          }
          }


          The output is:



          {
          "candidates": [{
          }, {
          }, {
          }],
          "errors": {
          "error1": {
          "message": "error1",
          "type": "ERROR"
          },
          "error2": {
          "message": "error2",
          "type": "WARNING"
          }
          }
          }


          Which has no keys and value as you see. Make sure that you printed not the message itself, but the result of JsonFormat.printer().print(). Basically, key and values you've seen are from internal toString() implementation of Protobuf Message.



          And the full class name for JsonFormat is com.google.protobuf.util.JsonFormat, not com.googlecode.protobuf.format.JsonFormat.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 16 '18 at 12:20









          madheadmadhead

          14.9k1389126




          14.9k1389126













          • Thank you for your help ! Indeed I used com.googlecode.protobuf.format.JsonFormat instead of com.google.protobuf.util.JsonFormat which was the issue. The googlecode one seems to be an out of date formatting util ?

            – CrazyGreenHand
            Nov 16 '18 at 16:50













          • I guess, yes, it's outdated. All Google results refer to com.google.protobuf.util.JsonFormat.

            – madhead
            Nov 16 '18 at 17:17



















          • Thank you for your help ! Indeed I used com.googlecode.protobuf.format.JsonFormat instead of com.google.protobuf.util.JsonFormat which was the issue. The googlecode one seems to be an out of date formatting util ?

            – CrazyGreenHand
            Nov 16 '18 at 16:50













          • I guess, yes, it's outdated. All Google results refer to com.google.protobuf.util.JsonFormat.

            – madhead
            Nov 16 '18 at 17:17

















          Thank you for your help ! Indeed I used com.googlecode.protobuf.format.JsonFormat instead of com.google.protobuf.util.JsonFormat which was the issue. The googlecode one seems to be an out of date formatting util ?

          – CrazyGreenHand
          Nov 16 '18 at 16:50







          Thank you for your help ! Indeed I used com.googlecode.protobuf.format.JsonFormat instead of com.google.protobuf.util.JsonFormat which was the issue. The googlecode one seems to be an out of date formatting util ?

          – CrazyGreenHand
          Nov 16 '18 at 16:50















          I guess, yes, it's outdated. All Google results refer to com.google.protobuf.util.JsonFormat.

          – madhead
          Nov 16 '18 at 17:17





          I guess, yes, it's outdated. All Google results refer to com.google.protobuf.util.JsonFormat.

          – madhead
          Nov 16 '18 at 17:17




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337220%2fprotobuf-map-type-json-format-uses-string-literal-key-and-value-not-the-actu%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Florida Star v. B. J. F.

          Danny Elfman

          Lugert, Oklahoma