From beabaa633417f0f694458102ceb7b54371858f16 Mon Sep 17 00:00:00 2001 From: Computer Network Investigation <121175071+JSCU-CNI@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:16:26 +0200 Subject: [PATCH] Pack booleans correctly when packing to JSON (#129) --- flow/record/jsonpacker.py | 7 ++++++- tests/test_json_packer.py | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/flow/record/jsonpacker.py b/flow/record/jsonpacker.py index 9004482..96c646e 100644 --- a/flow/record/jsonpacker.py +++ b/flow/record/jsonpacker.py @@ -41,15 +41,20 @@ def pack_obj(self, obj): if obj._desc.identifier not in self.descriptors: self.register(obj._desc, True) serial = obj._asdict() + if self.pack_descriptors: serial["_type"] = "record" serial["_recorddescriptor"] = obj._desc.identifier - # PYTHON2: Because "bytes" are also "str" we have to handle this here for field_type, field_name in obj._desc.get_field_tuples(): + # PYTHON2: Because "bytes" are also "str" we have to handle this here if field_type == "bytes" and isinstance(serial[field_name], str): serial[field_name] = base64.b64encode(serial[field_name]).decode() + # Boolean field types should be cast to a bool instead of staying ints + elif field_type == "boolean" and isinstance(serial[field_name], int): + serial[field_name] = bool(serial[field_name]) + return serial if isinstance(obj, RecordDescriptor): serial = { diff --git a/tests/test_json_packer.py b/tests/test_json_packer.py index 8b6119d..2ea2883 100644 --- a/tests/test_json_packer.py +++ b/tests/test_json_packer.py @@ -69,3 +69,24 @@ def test_record_descriptor_not_found(): packer = JsonRecordPacker() with pytest.raises(RecordDescriptorNotFound, match="No RecordDescriptor found for: .*test/descriptor_not_found"): packer.unpack(data) + + +def test_record_pack_bool_regression() -> None: + TestRecord = RecordDescriptor( + "test/record_pack_bool", + [ + ("varint", "some_varint"), + ("uint16", "some_uint"), + ("boolean", "some_boolean"), + ], + ) + + record = TestRecord(some_varint=1, some_uint=0, some_boolean=False) + packer = JsonRecordPacker() + + # pack to json string and check if some_boolean is false instead of 0 + data = packer.pack(record) + assert data.startswith('{"some_varint": 1, "some_uint": 0, "some_boolean": false, ') + + # pack the json string back to a record and make sure it is the same as before + assert packer.unpack(data) == record