Breaking change: Remove the deprecated always_print_primitive_fields option from Java, Python and C++ JSON parsers.

The replacement always_print_without_presence_fields should be used instead, which is very similar but has consistent handling of optional fields by not affecting them.

PiperOrigin-RevId: 604381178
pull/15704/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent 4c61b4364a
commit 2699579875
  1. 28
      java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
  2. 302
      java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
  3. 157
      python/google/protobuf/internal/json_format_test.py
  4. 33
      python/google/protobuf/json_format.py
  5. 10
      src/google/protobuf/json/internal/unparser.cc
  6. 10
      src/google/protobuf/json/internal/writer.h
  7. 2
      src/google/protobuf/json/json.cc
  8. 10
      src/google/protobuf/json/json.h
  9. 131
      src/google/protobuf/json/json_test.cc

@ -178,34 +178,6 @@ public class JsonFormat {
sortingMapKeys);
}
/**
* Creates a new {@link Printer} that will always print fields unless they are a message type or
* in a oneof.
*
* <p>Note that this does print Proto2 Optional but does not print Proto3 Optional fields, as
* the latter is represented using a synthetic oneof.
*
* <p>The new Printer clones all other configurations from the current {@link Printer}.
*
* @deprecated Prefer {@link #alwaysPrintFieldsWithNoPresence}
*/
@Deprecated
public Printer includingDefaultValueFields() {
if (shouldPrintDefaults != ShouldPrintDefaults.ONLY_IF_PRESENT) {
throw new IllegalStateException(
"JsonFormat includingDefaultValueFields has already been set.");
}
return new Printer(
registry,
oldRegistry,
ShouldPrintDefaults.ALWAYS_PRINT_EXCEPT_MESSAGES_AND_ONEOFS,
ImmutableSet.of(),
preservingProtoFieldNames,
omittingInsignificantWhitespace,
printingEnumsAsInts,
sortingMapKeys);
}
/**
* Creates a new {@link Printer} that will also print default-valued fields if their
* FieldDescriptors are found in the supplied set. Empty repeated fields and map fields will be

@ -1527,312 +1527,10 @@ public class JsonFormatTest {
+ " \"repeatedRecursive\": []\n"
+ "}";
// includingDefaultValueFields() and alwaysPrintFieldsWithNoPresence() should
// behave identically on the proto3 test message:
assertThat(JsonFormat.printer().includingDefaultValueFields().print(message))
.isEqualTo(expectedJsonWithDefaults);
assertThat(JsonFormat.printer().alwaysPrintFieldsWithNoPresence().print(message))
.isEqualTo(expectedJsonWithDefaults);
}
@Test
public void testDefaultValueForSpecificFieldsOptionProto3() throws Exception {
TestAllTypes message = TestAllTypes.getDefaultInstance();
Set<FieldDescriptor> fixedFields = new HashSet<>();
for (FieldDescriptor fieldDesc : TestAllTypes.getDescriptor().getFields()) {
if (fieldDesc.getName().contains("_fixed")) {
fixedFields.add(fieldDesc);
}
}
assertThat(JsonFormat.printer().includingDefaultValueFields(fixedFields).print(message))
.isEqualTo(
"{\n"
+ " \"optionalFixed32\": 0,\n"
+ " \"optionalFixed64\": \"0\",\n"
+ " \"repeatedFixed32\": [],\n"
+ " \"repeatedFixed64\": []\n"
+ "}");
TestAllTypes messageNonDefaults =
message.toBuilder().setOptionalInt64(1234).setOptionalFixed32(3232).build();
assertThat(
JsonFormat.printer().includingDefaultValueFields(fixedFields).print(messageNonDefaults))
.isEqualTo(
"{\n"
+ " \"optionalInt64\": \"1234\",\n"
+ " \"optionalFixed32\": 3232,\n"
+ " \"optionalFixed64\": \"0\",\n"
+ " \"repeatedFixed32\": [],\n"
+ " \"repeatedFixed64\": []\n"
+ "}");
}
@Test
public void testDefaultValueForSpecificFieldsProto3_doesntHonorMessageFields() throws Exception {
TestAllTypes message = TestAllTypes.getDefaultInstance();
Set<FieldDescriptor> fixedFields =
ImmutableSet.of(
TestAllTypes.getDescriptor().findFieldByName("optional_bool"),
TestAllTypes.getDescriptor().findFieldByName("optional_recursive"));
assertThat(JsonFormat.printer().includingDefaultValueFields(fixedFields).print(message))
.isEqualTo("{\n \"optionalBool\": false\n}");
}
@Test
public void testRejectChangingDefaultFieldOptionMultipleTimes() throws Exception {
Set<FieldDescriptor> fixedFields = new HashSet<>();
for (FieldDescriptor fieldDesc : TestAllTypes.getDescriptor().getFields()) {
if (fieldDesc.getName().contains("_fixed")) {
fixedFields.add(fieldDesc);
}
}
try {
JsonFormat.printer().includingDefaultValueFields().includingDefaultValueFields();
assertWithMessage("IllegalStateException is expected.").fail();
} catch (IllegalStateException e) {
// Expected.
assertWithMessage("Exception message should mention includingDefaultValueFields.")
.that(e.getMessage().contains("includingDefaultValueFields"))
.isTrue();
}
try {
JsonFormat.printer().includingDefaultValueFields().includingDefaultValueFields(fixedFields);
assertWithMessage("IllegalStateException is expected.").fail();
} catch (IllegalStateException e) {
// Expected.
assertWithMessage("Exception message should mention includingDefaultValueFields.")
.that(e.getMessage().contains("includingDefaultValueFields"))
.isTrue();
}
try {
JsonFormat.printer().includingDefaultValueFields(fixedFields).includingDefaultValueFields();
assertWithMessage("IllegalStateException is expected.").fail();
} catch (IllegalStateException e) {
// Expected.
assertWithMessage("Exception message should mention includingDefaultValueFields.")
.that(e.getMessage().contains("includingDefaultValueFields"))
.isTrue();
}
try {
JsonFormat.printer()
.includingDefaultValueFields(fixedFields)
.includingDefaultValueFields(fixedFields);
assertWithMessage("IllegalStateException is expected.").fail();
} catch (IllegalStateException e) {
// Expected.
assertWithMessage("Exception message should mention includingDefaultValueFields.")
.that(e.getMessage().contains("includingDefaultValueFields"))
.isTrue();
}
Set<FieldDescriptor> intFields = new HashSet<>();
for (FieldDescriptor fieldDesc : TestAllTypes.getDescriptor().getFields()) {
if (fieldDesc.getName().contains("_int")) {
intFields.add(fieldDesc);
}
}
try {
JsonFormat.printer()
.includingDefaultValueFields(intFields)
.includingDefaultValueFields(fixedFields);
assertWithMessage("IllegalStateException is expected.").fail();
} catch (IllegalStateException e) {
// Expected.
assertWithMessage("Exception message should mention includingDefaultValueFields.")
.that(e.getMessage().contains("includingDefaultValueFields"))
.isTrue();
}
try {
JsonFormat.printer().includingDefaultValueFields(null);
assertWithMessage("IllegalArgumentException is expected.").fail();
} catch (IllegalArgumentException e) {
// Expected.
assertWithMessage("Exception message should mention includingDefaultValueFields.")
.that(e.getMessage().contains("includingDefaultValueFields"))
.isTrue();
}
try {
JsonFormat.printer().includingDefaultValueFields(Collections.<FieldDescriptor>emptySet());
assertWithMessage("IllegalArgumentException is expected.").fail();
} catch (IllegalArgumentException e) {
// Expected.
assertWithMessage("Exception message should mention includingDefaultValueFields.")
.that(e.getMessage().contains("includingDefaultValueFields"))
.isTrue();
}
}
@Test
public void testDefaultValuesOptionProto3Maps() throws Exception {
TestMap mapMessage = TestMap.getDefaultInstance();
assertThat(JsonFormat.printer().print(mapMessage)).isEqualTo("{\n}");
assertThat(JsonFormat.printer().includingDefaultValueFields().print(mapMessage))
.isEqualTo(
"{\n"
+ " \"int32ToInt32Map\": {\n"
+ " },\n"
+ " \"int64ToInt32Map\": {\n"
+ " },\n"
+ " \"uint32ToInt32Map\": {\n"
+ " },\n"
+ " \"uint64ToInt32Map\": {\n"
+ " },\n"
+ " \"sint32ToInt32Map\": {\n"
+ " },\n"
+ " \"sint64ToInt32Map\": {\n"
+ " },\n"
+ " \"fixed32ToInt32Map\": {\n"
+ " },\n"
+ " \"fixed64ToInt32Map\": {\n"
+ " },\n"
+ " \"sfixed32ToInt32Map\": {\n"
+ " },\n"
+ " \"sfixed64ToInt32Map\": {\n"
+ " },\n"
+ " \"boolToInt32Map\": {\n"
+ " },\n"
+ " \"stringToInt32Map\": {\n"
+ " },\n"
+ " \"int32ToInt64Map\": {\n"
+ " },\n"
+ " \"int32ToUint32Map\": {\n"
+ " },\n"
+ " \"int32ToUint64Map\": {\n"
+ " },\n"
+ " \"int32ToSint32Map\": {\n"
+ " },\n"
+ " \"int32ToSint64Map\": {\n"
+ " },\n"
+ " \"int32ToFixed32Map\": {\n"
+ " },\n"
+ " \"int32ToFixed64Map\": {\n"
+ " },\n"
+ " \"int32ToSfixed32Map\": {\n"
+ " },\n"
+ " \"int32ToSfixed64Map\": {\n"
+ " },\n"
+ " \"int32ToFloatMap\": {\n"
+ " },\n"
+ " \"int32ToDoubleMap\": {\n"
+ " },\n"
+ " \"int32ToBoolMap\": {\n"
+ " },\n"
+ " \"int32ToStringMap\": {\n"
+ " },\n"
+ " \"int32ToBytesMap\": {\n"
+ " },\n"
+ " \"int32ToMessageMap\": {\n"
+ " },\n"
+ " \"int32ToEnumMap\": {\n"
+ " }\n"
+ "}");
}
@Test
public void testDefaultValueOptionsProto3Oneofs() throws Exception {
TestOneof oneofMessage = TestOneof.getDefaultInstance();
assertThat(JsonFormat.printer().print(oneofMessage)).isEqualTo("{\n}");
assertThat(JsonFormat.printer().includingDefaultValueFields().print(oneofMessage))
.isEqualTo("{\n}");
assertThat(JsonFormat.printer().alwaysPrintFieldsWithNoPresence().print(oneofMessage))
.isEqualTo("{\n}");
oneofMessage = TestOneof.newBuilder().setOneofInt32(42).build();
assertThat(JsonFormat.printer().print(oneofMessage)).isEqualTo("{\n \"oneofInt32\": 42\n}");
assertThat(JsonFormat.printer().includingDefaultValueFields().print(oneofMessage))
.isEqualTo("{\n \"oneofInt32\": 42\n}");
assertThat(JsonFormat.printer().alwaysPrintFieldsWithNoPresence().print(oneofMessage))
.isEqualTo("{\n \"oneofInt32\": 42\n}");
TestOneof.Builder oneofBuilder = TestOneof.newBuilder();
mergeFromJson("{\n" + " \"oneofNullValue\": null \n" + "}", oneofBuilder);
oneofMessage = oneofBuilder.build();
assertThat(JsonFormat.printer().print(oneofMessage))
.isEqualTo("{\n \"oneofNullValue\": null\n}");
assertThat(JsonFormat.printer().includingDefaultValueFields().print(oneofMessage))
.isEqualTo("{\n \"oneofNullValue\": null\n}");
assertThat(JsonFormat.printer().alwaysPrintFieldsWithNoPresence().print(oneofMessage))
.isEqualTo("{\n \"oneofNullValue\": null\n}");
}
@Test
public void testIncludingDefaultValueOptionsWithProto2Optional() throws Exception {
TestAllTypesProto2 message = TestAllTypesProto2.getDefaultInstance();
assertThat(JsonFormat.printer().print(message)).isEqualTo("{\n}");
// includingDefaultValueFields() and alwaysPrintFieldsWithNoPresence()
// behave differently on a proto2 message: the former includes the proto2 explicit presence
// fields and the latter does not.
assertThat(JsonFormat.printer().includingDefaultValueFields().print(message))
.isEqualTo(
"{\n"
+ " \"optionalInt32\": 0,\n"
+ " \"optionalInt64\": \"0\",\n"
+ " \"optionalUint32\": 0,\n"
+ " \"optionalUint64\": \"0\",\n"
+ " \"optionalSint32\": 0,\n"
+ " \"optionalSint64\": \"0\",\n"
+ " \"optionalFixed32\": 0,\n"
+ " \"optionalFixed64\": \"0\",\n"
+ " \"optionalSfixed32\": 0,\n"
+ " \"optionalSfixed64\": \"0\",\n"
+ " \"optionalFloat\": 0.0,\n"
+ " \"optionalDouble\": 0.0,\n"
+ " \"optionalBool\": false,\n"
+ " \"optionalString\": \"\",\n"
+ " \"optionalBytes\": \"\",\n"
+ " \"optionalNestedEnum\": \"FOO\",\n"
+ " \"repeatedInt32\": [],\n"
+ " \"repeatedInt64\": [],\n"
+ " \"repeatedUint32\": [],\n"
+ " \"repeatedUint64\": [],\n"
+ " \"repeatedSint32\": [],\n"
+ " \"repeatedSint64\": [],\n"
+ " \"repeatedFixed32\": [],\n"
+ " \"repeatedFixed64\": [],\n"
+ " \"repeatedSfixed32\": [],\n"
+ " \"repeatedSfixed64\": [],\n"
+ " \"repeatedFloat\": [],\n"
+ " \"repeatedDouble\": [],\n"
+ " \"repeatedBool\": [],\n"
+ " \"repeatedString\": [],\n"
+ " \"repeatedBytes\": [],\n"
+ " \"repeatedNestedMessage\": [],\n"
+ " \"repeatedNestedEnum\": [],\n"
+ " \"optionalAliasedEnum\": \"ALIAS_FOO\",\n"
+ " \"repeatedRecursive\": []\n"
+ "}");
assertThat(JsonFormat.printer().alwaysPrintFieldsWithNoPresence().print(message))
.isEqualTo(
"{\n"
+ " \"repeatedInt32\": [],\n"
+ " \"repeatedInt64\": [],\n"
+ " \"repeatedUint32\": [],\n"
+ " \"repeatedUint64\": [],\n"
+ " \"repeatedSint32\": [],\n"
+ " \"repeatedSint64\": [],\n"
+ " \"repeatedFixed32\": [],\n"
+ " \"repeatedFixed64\": [],\n"
+ " \"repeatedSfixed32\": [],\n"
+ " \"repeatedSfixed64\": [],\n"
+ " \"repeatedFloat\": [],\n"
+ " \"repeatedDouble\": [],\n"
+ " \"repeatedBool\": [],\n"
+ " \"repeatedString\": [],\n"
+ " \"repeatedBytes\": [],\n"
+ " \"repeatedNestedMessage\": [],\n"
+ " \"repeatedNestedEnum\": [],\n"
+ " \"repeatedRecursive\": []\n"
+ "}");
}
@Test
public void testDefaultValueForSpecificFieldsOptionProto2() throws Exception {
TestAllTypesProto2 message = TestAllTypesProto2.getDefaultInstance();

@ -266,65 +266,6 @@ class JsonFormatTest(JsonFormatBase):
json_format.Parse(text, message)
self.assertEqual(message.int32_value, 1)
def testAlwaysSeriliaze(self):
message = json_format_proto3_pb2.TestMessage(string_value='foo')
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
)
),
json.loads(
'{'
'"repeatedStringValue": [],'
'"stringValue": "foo",'
'"repeatedBoolValue": [],'
'"repeatedUint32Value": [],'
'"repeatedInt32Value": [],'
'"enumValue": "FOO",'
'"int32Value": 0,'
'"floatValue": 0,'
'"int64Value": "0",'
'"uint32Value": 0,'
'"repeatedBytesValue": [],'
'"repeatedUint64Value": [],'
'"repeatedDoubleValue": [],'
'"bytesValue": "",'
'"boolValue": false,'
'"repeatedEnumValue": [],'
'"uint64Value": "0",'
'"doubleValue": 0,'
'"repeatedFloatValue": [],'
'"repeatedInt64Value": [],'
'"repeatedMessageValue": []}'
),
)
parsed_message = json_format_proto3_pb2.TestMessage()
self.CheckParseBack(message, parsed_message)
def testProto3Optional_IncludingDefaultValueFields(self):
message = test_proto3_optional_pb2.TestProto3Optional()
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
)
),
json.loads('{"repeatedInt32": [], "repeatedNestedMessage": []}'),
)
message.optional_int32 = 0
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
)
),
json.loads(
'{"optionalInt32": 0,"repeatedInt32": [],'
' "repeatedNestedMessage": []}'
),
)
def testProto3Optional_IncludingDefaultValueWithoutPresenceFields(self):
message = test_proto3_optional_pb2.TestProto3Optional()
self.assertEqual(
@ -348,44 +289,6 @@ class JsonFormatTest(JsonFormatBase):
),
)
def testProto2_IncludingDefaultValueFields(self):
message = test_proto2_pb2.TestProto2()
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
)
),
json.loads("""{
"optionalBool":false,
"optionalBytes":"",
"optionalDouble":0.0,
"optionalInt32":0,
"optionalNestedEnum":"UNSPECIFIED",
"optionalString":"",
"repeatedInt32":[],
"repeatedNestedMessage": []
}"""),
)
message.optional_int32 = 99
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
)
),
json.loads("""{
"optionalBool":false,
"optionalBytes":"",
"optionalDouble":0.0,
"optionalInt32":99,
"optionalNestedEnum":"UNSPECIFIED",
"optionalString":"",
"repeatedInt32":[],
"repeatedNestedMessage": []
}"""),
)
def testProto2_IncludingDefaultValueWithoutPresenceFields(self):
message = test_proto2_pb2.TestProto2()
self.assertEqual(
@ -423,7 +326,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -454,7 +357,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=False
message, always_print_fields_with_no_presence=False
)
),
json.loads(
@ -476,12 +379,16 @@ class JsonFormatTest(JsonFormatBase):
message = json_format_proto3_pb2.TestOneof()
# Always print does not affect oneof fields.
self.assertEqual(
json_format.MessageToJson(message, including_default_value_fields=True),
json_format.MessageToJson(
message, always_print_fields_with_no_presence=True
),
'{}',
)
message.oneof_int32_value = 0
self.assertEqual(
json_format.MessageToJson(message, including_default_value_fields=True),
json_format.MessageToJson(
message, always_print_fields_with_no_presence=True
),
'{\n "oneofInt32Value": 0\n}',
)
parsed_message = json_format_proto3_pb2.TestOneof()
@ -526,7 +433,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -570,7 +477,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -594,7 +501,9 @@ class JsonFormatTest(JsonFormatBase):
message.value.paths.append('foo.bar')
message.value.paths.append('bar')
self.assertEqual(
json_format.MessageToJson(message, including_default_value_fields=True),
json_format.MessageToJson(
message, always_print_fields_with_no_presence=True
),
'{\n "value": "foo.bar,bar"\n}',
)
parsed_message = json_format_proto3_pb2.TestFieldMask()
@ -602,7 +511,9 @@ class JsonFormatTest(JsonFormatBase):
message.value.Clear()
self.assertEqual(
json_format.MessageToJson(message, including_default_value_fields=True),
json_format.MessageToJson(
message, always_print_fields_with_no_presence=True
),
'{\n "value": ""\n}',
)
self.CheckParseBack(message, parsed_message)
@ -619,7 +530,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -661,7 +572,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=False
message, always_print_fields_with_no_presence=False
)
),
json.loads(
@ -698,7 +609,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=False
message, always_print_fields_with_no_presence=False
)
),
json.loads(
@ -712,7 +623,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=False
message, always_print_fields_with_no_presence=False
)
),
json.loads(
@ -754,7 +665,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=False
message, always_print_fields_with_no_presence=False
)
),
json.loads(
@ -793,7 +704,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -829,7 +740,7 @@ class JsonFormatTest(JsonFormatBase):
message.value.Pack(test_message)
self.assertEqual(
json_format.MessageToJson(
message, including_default_value_fields=False
message, always_print_fields_with_no_presence=False
)[0:68],
'{\n'
' "value": {\n'
@ -845,7 +756,7 @@ class JsonFormatTest(JsonFormatBase):
with self.assertRaises(TypeError) as cm:
json_format.MessageToJson(
message,
including_default_value_fields=True,
always_print_fields_with_no_presence=True,
descriptor_pool=empty_pool,
)
self.assertEqual(
@ -862,7 +773,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -880,7 +791,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -898,7 +809,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -917,7 +828,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -935,7 +846,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -954,7 +865,7 @@ class JsonFormatTest(JsonFormatBase):
self.assertEqual(
json.loads(
json_format.MessageToJson(
message, including_default_value_fields=True
message, always_print_fields_with_no_presence=True
)
),
json.loads(
@ -1489,24 +1400,24 @@ class JsonFormatTest(JsonFormatBase):
'{\n "int32_value": 12345\n}',
json_format.MessageToJson(
message,
including_default_value_fields=False,
always_print_fields_with_no_presence=False,
preserving_proto_field_name=True,
),
)
# When including_default_value_fields is True.
# When always_print_fields_with_no_presence is True.
message = json_format_proto3_pb2.TestTimestamp()
self.assertEqual(
'{\n "repeatedValue": []\n}',
json_format.MessageToJson(
message,
including_default_value_fields=True,
always_print_fields_with_no_presence=True,
),
)
self.assertEqual(
'{\n "repeated_value": []\n}',
json_format.MessageToJson(
message,
including_default_value_fields=True,
always_print_fields_with_no_presence=True,
preserving_proto_field_name=True,
),
)

@ -72,7 +72,6 @@ class ParseError(Error):
def MessageToJson(
message,
including_default_value_fields=False,
preserving_proto_field_name=False,
indent=2,
sort_keys=False,
@ -86,12 +85,6 @@ def MessageToJson(
Args:
message: The protocol buffers message instance to serialize.
including_default_value_fields: (DEPRECATED: use
always_print_fields_with_no_presence which correctly treats proto2
and proto3 optionals the same). If True, fields without presence (implicit
presence scalars, repeated fields, and map fields) and Proto2 optional
scalars will always be serialized. Singular message fields, oneof fields
and Proto3 optional scalars are not affected by this option.
always_print_fields_with_no_presence: If True, fields without
presence (implicit presence scalars, repeated fields, and map fields) will
always be serialized. Any field that supports presence is not affected by
@ -114,7 +107,6 @@ def MessageToJson(
A string containing the JSON formatted protocol buffer message.
"""
printer = _Printer(
including_default_value_fields,
preserving_proto_field_name,
use_integers_for_enums,
descriptor_pool,
@ -126,7 +118,6 @@ def MessageToJson(
def MessageToDict(
message,
including_default_value_fields=False,
always_print_fields_with_no_presence=False,
preserving_proto_field_name=False,
use_integers_for_enums=False,
@ -139,12 +130,6 @@ def MessageToDict(
Args:
message: The protocol buffers message instance to serialize.
including_default_value_fields: (DEPRECATED: use
always_print_fields_with_no_presence to correctly treats proto2
and proto3 optional the same). If True, fields without presence (implicit
presence scalars, repeated fields, and map fields) and Proto2 optional
scalars will always be serialized. Singular message fields, oneof fields
and Proto3 optional scalars are not affected by this option.
always_print_fields_with_no_presence: If True, fields without
presence (implicit presence scalars, repeated fields, and map fields) will
always be serialized. Any field that supports presence is not affected by
@ -161,7 +146,6 @@ def MessageToDict(
A dict representation of the protocol buffer message.
"""
printer = _Printer(
including_default_value_fields,
preserving_proto_field_name,
use_integers_for_enums,
descriptor_pool,
@ -185,14 +169,12 @@ class _Printer(object):
def __init__(
self,
including_default_value_fields=False,
preserving_proto_field_name=False,
use_integers_for_enums=False,
descriptor_pool=None,
float_precision=None,
always_print_fields_with_no_presence=False,
):
self.including_default_value_fields = including_default_value_fields
self.always_print_fields_with_no_presence = (
always_print_fields_with_no_presence
)
@ -256,23 +238,10 @@ class _Printer(object):
# Serialize default value if including_default_value_fields is True.
if (
self.including_default_value_fields
or self.always_print_fields_with_no_presence
self.always_print_fields_with_no_presence
):
message_descriptor = message.DESCRIPTOR
for field in message_descriptor.fields:
# including_default_value doesn't apply to singular messages or any
# field with a containing oneof (including proto3 optionals which use
# a synthetic oneof).
if self.including_default_value_fields and (
(
field.label != descriptor.FieldDescriptor.LABEL_REPEATED
and field.cpp_type
== descriptor.FieldDescriptor.CPPTYPE_MESSAGE
)
or field.containing_oneof
):
continue
# always_print_fields_with_no_presence doesn't apply to
# any field which supports presence.

@ -433,9 +433,6 @@ absl::Status WriteField(JsonWriter& writer, const Msg<Traits>& msg,
} else if (Traits::IsRepeated(field)) {
return WriteRepeated<Traits>(writer, msg, field);
} else if (Traits::GetSize(field, msg) == 0) {
// We can only get here if one of the always_print options is true.
ABSL_DCHECK(writer.options().always_print_primitive_fields ||
writer.options().always_print_fields_with_no_presence);
if (Traits::FieldType(field) == FieldDescriptor::TYPE_GROUP) {
// We do not yet have full group support, but this is required so that we
@ -459,12 +456,7 @@ absl::Status WriteFields(JsonWriter& writer, const Msg<Traits>& msg,
Field<Traits> field = Traits::FieldByIndex(desc, i);
bool has = Traits::GetSize(field, msg) > 0;
if (writer.options().always_print_primitive_fields) {
bool is_singular_message =
!Traits::IsRepeated(field) &&
Traits::FieldType(field) == FieldDescriptor::TYPE_MESSAGE;
has |= !is_singular_message && !Traits::IsOneof(field);
}
if (writer.options().always_print_fields_with_no_presence) {
has |= Traits::IsRepeated(field) || Traits::IsImplicitPresence(field);
}

@ -36,16 +36,6 @@ struct WriterOptions {
// Whether to add spaces, line breaks and indentation to make the JSON output
// easy to read.
bool add_whitespace = false;
// Whether to always print the following types of fields even if they would
// otherwise be omitted:
// - Implicit presence fields set to their 0 value
// - Empty lists and maps
// - Proto2 optional and required scalar fields which are not present (but not
// Proto3 optional scalar fields).
// Note: This option is deprecated in favor of
// always_print_fields_with_no_presence which treats proto2 and proto3
// optionals the same and will be removed in an upcoming release.
bool always_print_primitive_fields = false;
// Whether to always print fields which do not support presence if they would
// otherwise be omitted, namely:
// - Implicit presence fields set to their 0 value

@ -33,7 +33,6 @@ absl::Status BinaryToJsonStream(google::protobuf::util::TypeResolver* resolver,
opts.add_whitespace = options.add_whitespace;
opts.preserve_proto_field_names = options.preserve_proto_field_names;
opts.always_print_enums_as_ints = options.always_print_enums_as_ints;
opts.always_print_primitive_fields = options.always_print_primitive_fields;
opts.always_print_fields_with_no_presence =
options.always_print_fields_with_no_presence;
opts.unquote_int64_if_possible = options.unquote_int64_if_possible;
@ -89,7 +88,6 @@ absl::Status MessageToJsonString(const Message& message, std::string* output,
opts.add_whitespace = options.add_whitespace;
opts.preserve_proto_field_names = options.preserve_proto_field_names;
opts.always_print_enums_as_ints = options.always_print_enums_as_ints;
opts.always_print_primitive_fields = options.always_print_primitive_fields;
opts.always_print_fields_with_no_presence =
options.always_print_fields_with_no_presence;
opts.unquote_int64_if_possible = options.unquote_int64_if_possible;

@ -39,16 +39,6 @@ struct PrintOptions {
// Whether to add spaces, line breaks and indentation to make the JSON output
// easy to read.
bool add_whitespace = false;
// Whether to always print the following types of fields even if they would
// otherwise be omitted:
// - Implicit presence fields set to their 0 value
// - Empty lists and maps
// - Proto2 optional and required scalar fields which are not present (but not
// Proto3 optional scalar fields).
// Note: This option is deprecated in favor of
// always_print_fields_with_no_presence which treats proto2 and proto3
// optionals the same and will be removed in an upcoming release.
bool always_print_primitive_fields = false;
// Whether to always print fields which do not support presence if they would
// otherwise be omitted, namely:
// - Implicit presence fields set to their 0 value

@ -173,107 +173,8 @@ TEST_P(JsonTest, TestWhitespaces) {
)"));
}
TEST_P(JsonTest, TestDefaultValues) {
TestMessage m;
EXPECT_THAT(ToJson(m), IsOkAndHolds("{}"));
PrintOptions options;
options.always_print_primitive_fields = true;
EXPECT_THAT(ToJson(m, options), IsOkAndHolds(R"({"boolValue":false,)"
R"("int32Value":0,)"
R"("int64Value":"0",)"
R"("uint32Value":0,)"
R"("uint64Value":"0",)"
R"("floatValue":0,)"
R"("doubleValue":0,)"
R"("stringValue":"",)"
R"("bytesValue":"",)"
R"("enumValue":"FOO",)"
R"("repeatedBoolValue":[],)"
R"("repeatedInt32Value":[],)"
R"("repeatedInt64Value":[],)"
R"("repeatedUint32Value":[],)"
R"("repeatedUint64Value":[],)"
R"("repeatedFloatValue":[],)"
R"("repeatedDoubleValue":[],)"
R"("repeatedStringValue":[],)"
R"("repeatedBytesValue":[],)"
R"("repeatedEnumValue":[],)"
R"("repeatedMessageValue":[])"
"}"));
m.set_string_value("i am a test string value");
m.set_bytes_value("i am a test bytes value");
m.set_optional_bool_value(false);
m.set_optional_string_value("");
m.set_optional_bytes_value("");
EXPECT_THAT(ToJson(m, options),
IsOkAndHolds(R"({"boolValue":false,)"
R"("int32Value":0,)"
R"("int64Value":"0",)"
R"("uint32Value":0,)"
R"("uint64Value":"0",)"
R"("floatValue":0,)"
R"("doubleValue":0,)"
R"("stringValue":"i am a test string value",)"
R"("bytesValue":"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=",)"
R"("enumValue":"FOO",)"
R"("repeatedBoolValue":[],)"
R"("repeatedInt32Value":[],)"
R"("repeatedInt64Value":[],)"
R"("repeatedUint32Value":[],)"
R"("repeatedUint64Value":[],)"
R"("repeatedFloatValue":[],)"
R"("repeatedDoubleValue":[],)"
R"("repeatedStringValue":[],)"
R"("repeatedBytesValue":[],)"
R"("repeatedEnumValue":[],)"
R"("repeatedMessageValue":[],)"
R"("optionalBoolValue":false,)"
R"("optionalStringValue":"",)"
R"("optionalBytesValue":"")"
"}"));
EXPECT_THAT(
ToJson(protobuf_unittest::TestAllTypes(), options),
IsOkAndHolds(
R"({"optionalInt32":0,"optionalInt64":"0","optionalUint32":0,)"
R"("optionalUint64":"0","optionalSint32":0,"optionalSint64":"0","optionalFixed32":0,)"
R"("optionalFixed64":"0","optionalSfixed32":0,"optionalSfixed64":"0",)"
R"("optionalFloat":0,"optionalDouble":0,"optionalBool":false,"optionalString":"",)"
R"("optionalBytes":"","optionalgroup":null,"optionalNestedEnum":"FOO","optionalForeignEnum":"FOREIGN_FOO",)"
R"("optionalImportEnum":"IMPORT_FOO","optionalStringPiece":"","optionalCord":"",)"
R"("repeatedInt32":[],"repeatedInt64":[],"repeatedUint32":[],"repeatedUint64":[],)"
R"("repeatedSint32":[],"repeatedSint64":[],"repeatedFixed32":[],"repeatedFixed64":[],)"
R"("repeatedSfixed32":[],"repeatedSfixed64":[],"repeatedFloat":[],"repeatedDouble":[],)"
R"("repeatedBool":[],"repeatedString":[],"repeatedBytes":[],"repeatedgroup":[],)"
R"("repeatedNestedMessage":[],"repeatedForeignMessage":[],"repeatedImportMessage":[],)"
R"("repeatedNestedEnum":[],"repeatedForeignEnum":[],"repeatedImportEnum":[],)"
R"("repeatedStringPiece":[],"repeatedCord":[],"repeatedLazyMessage":[],"defaultInt32":41,)"
R"("defaultInt64":"42","defaultUint32":43,"defaultUint64":"44","defaultSint32":-45,)"
R"("defaultSint64":"46","defaultFixed32":47,"defaultFixed64":"48","defaultSfixed32":49,)"
R"("defaultSfixed64":"-50","defaultFloat":51.5,"defaultDouble":52000,"defaultBool":true,)"
R"("defaultString":"hello","defaultBytes":"d29ybGQ=","defaultNestedEnum":"BAR",)"
R"("defaultForeignEnum":"FOREIGN_BAR","defaultImportEnum":"IMPORT_BAR",)"
R"("defaultStringPiece":"abc","defaultCord":"123"})"));
EXPECT_THAT(
ToJson(protobuf_unittest::TestExtremeDefaultValues(), options),
IsOkAndHolds(
R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")"
R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)"
R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807",)"
R"("utf8String":"","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)"
R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)"
R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0,)"
R"("nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0,)"
R"("cppTrigraph":"? ? ?? ?? ??? ??/ ??-","reallySmallInt32":-2147483648)"
R"(,"reallySmallInt64":"-9223372036854775808","stringWithZero":"hel\u0000lo")"
R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")"
R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})"));
}
TEST_P(JsonTest, TestAlwaysPrintWithoutPresenceFields) {
TEST_P(JsonTest, TestAlwaysPrintFieldsWithNoPresence) {
TestMessage m;
EXPECT_THAT(ToJson(m), IsOkAndHolds("{}"));
@ -423,7 +324,7 @@ TEST_P(JsonTest, TestPrintEnumsAsIntsWithDefaultValue) {
PrintOptions print_options;
print_options.always_print_enums_as_ints = true;
print_options.always_print_primitive_fields = true;
print_options.always_print_fields_with_no_presence = true;
auto printed = ToJson(orig, print_options);
ASSERT_THAT(
@ -437,21 +338,6 @@ TEST_P(JsonTest, TestPrintEnumsAsIntsWithDefaultValue) {
EXPECT_EQ(parsed->enum_value3(), proto3::BAR);
}
TEST_P(JsonTest, TestPrintProto2EnumAsIntWithDefaultValue) {
protobuf_unittest::TestDefaultEnumValue orig;
PrintOptions print_options;
print_options.always_print_enums_as_ints = true;
print_options.always_print_primitive_fields = true;
auto printed = ToJson(orig, print_options);
ASSERT_THAT(printed, IsOkAndHolds("{\"enumValue\":2}"));
auto parsed = ToProto<protobuf_unittest::TestDefaultEnumValue>(*printed);
ASSERT_OK(parsed);
EXPECT_EQ(parsed->enum_value(), protobuf_unittest::DEFAULT);
}
TEST_P(JsonTest, QuotedEnumValue) {
auto m = ToProto<TestEnumValue>(R"json(
@ -634,7 +520,7 @@ TEST_P(JsonTest, RepeatedMapKey) {
TEST_P(JsonTest, ParsePrimitiveMapIn) {
MapIn message;
PrintOptions print_options;
print_options.always_print_primitive_fields = true;
print_options.always_print_fields_with_no_presence = true;
auto printed = ToJson(message, print_options);
ASSERT_THAT(
ToJson(message, print_options),
@ -648,7 +534,7 @@ TEST_P(JsonTest, ParsePrimitiveMapIn) {
TEST_P(JsonTest, PrintPrimitiveOneof) {
TestOneof message;
PrintOptions options;
options.always_print_primitive_fields = true;
options.always_print_fields_with_no_presence = true;
message.mutable_oneof_message_value();
EXPECT_THAT(ToJson(message, options),
IsOkAndHolds(R"({"oneofMessageValue":{"value":0}})"));
@ -1375,15 +1261,6 @@ TEST_P(JsonTest, HtmlEscape) {
EXPECT_THAT(ToJson(m),
IsOkAndHolds(R"({"stringValue":"\u003c/script\u003e"})"));
proto3::TestEvilJson m2;
PrintOptions opts;
opts.always_print_primitive_fields = true;
EXPECT_THAT(
ToJson(m2, opts),
IsOkAndHolds(
R"({"regular_name":0,"\u003c/script\u003e":0,)"
R"("unbalanced\"quotes":0,)"
R"("\"\u003cscript\u003ealert('hello!);\u003c/script\u003e":0})"));
}
TEST_P(JsonTest, FieldOrder) {

Loading…
Cancel
Save