This is an automated email from the ASF dual-hosted git repository.

piotr pushed a commit to branch non_string_header_key
in repository https://gitbox.apache.org/repos/asf/iggy.git

commit fe92af98b5644ce6cb9ce3407ed48134b7cdaa1e
Author: spetz <[email protected]>
AuthorDate: Thu Jan 29 21:25:05 2026 +0100

    Always include user_headers in JSON response (empty array when none)
---
 core/common/src/types/message/iggy_message.rs      | 41 +++++++++---
 .../main/java/org/apache/iggy/message/Message.java | 72 ++++++++--------------
 2 files changed, 58 insertions(+), 55 deletions(-)

diff --git a/core/common/src/types/message/iggy_message.rs 
b/core/common/src/types/message/iggy_message.rs
index f34b2b272..49fe0b89b 100644
--- a/core/common/src/types/message/iggy_message.rs
+++ b/core/common/src/types/message/iggy_message.rs
@@ -545,24 +545,25 @@ impl Serialize for IggyMessage {
         use base64::{Engine as _, engine::general_purpose::STANDARD};
         use serde::ser::SerializeStruct;
 
-        let field_count = 2 + self.user_headers.is_some() as usize;
-
-        let mut state = serializer.serialize_struct("IggyMessage", 
field_count)?;
+        let mut state = serializer.serialize_struct("IggyMessage", 3)?;
         state.serialize_field("header", &self.header)?;
 
         let base64_payload = STANDARD.encode(&self.payload);
         state.serialize_field("payload", &base64_payload)?;
 
-        if self.user_headers.is_some() {
+        let entries: Vec<HeaderEntry> = if self.user_headers.is_some() {
             let headers_map = 
self.user_headers_map().map_err(serde::ser::Error::custom)?;
             if let Some(map) = headers_map {
-                let entries: Vec<HeaderEntry> = map
-                    .into_iter()
+                map.into_iter()
                     .map(|(key, value)| HeaderEntry { key, value })
-                    .collect();
-                state.serialize_field("user_headers", &entries)?;
+                    .collect()
+            } else {
+                Vec::new()
             }
-        }
+        } else {
+            Vec::new()
+        };
+        state.serialize_field("user_headers", &entries)?;
 
         state.end()
     }
@@ -732,6 +733,28 @@ mod tests {
         assert_eq!(original.payload, decoded.payload);
     }
 
+    #[test]
+    fn test_json_serialization_without_headers() {
+        let original = IggyMessage::builder()
+            .id(1)
+            .payload(Bytes::from("test"))
+            .build()
+            .expect("Message creation should not fail");
+
+        let json = serde_json::to_string(&original).expect("JSON serialization 
should not fail");
+
+        assert!(json.contains("\"user_headers\":[]"));
+
+        let deserialized: IggyMessage =
+            serde_json::from_str(&json).expect("JSON deserialization should 
not fail");
+
+        assert_eq!(original.header.id, deserialized.header.id);
+        assert_eq!(original.payload, deserialized.payload);
+
+        let headers_map = deserialized.user_headers_map().unwrap();
+        assert!(headers_map.map(|m| m.is_empty()).unwrap_or(true));
+    }
+
     #[test]
     fn test_json_serialization_with_headers() {
         let mut headers = HashMap::new();
diff --git 
a/foreign/java/java-sdk/src/main/java/org/apache/iggy/message/Message.java 
b/foreign/java/java-sdk/src/main/java/org/apache/iggy/message/Message.java
index 4143b52b5..414062504 100644
--- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/message/Message.java
+++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/message/Message.java
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonSetter;
 import com.fasterxml.jackson.annotation.Nulls;
+
 import java.math.BigInteger;
 import java.util.Base64;
 import java.util.Collections;
@@ -30,19 +31,13 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public record Message(
-    MessageHeader header,
-    byte[] payload,
-    Map<HeaderKey, HeaderValue> userHeaders
-) {
+public record Message(MessageHeader header, byte[] payload, Map<HeaderKey, 
HeaderValue> userHeaders) {
     @JsonCreator
     public static Message fromJson(
-        @JsonProperty("header") MessageHeader header,
-        @JsonProperty("payload") String base64Payload,
-        @JsonProperty(value = "user_headers", required = false) @JsonSetter(
-            nulls = Nulls.AS_EMPTY
-        ) List<HeaderEntry> userHeadersList
-    ) {
+            @JsonProperty("header") MessageHeader header,
+            @JsonProperty("payload") String base64Payload,
+            @JsonProperty(value = "user_headers", required = false) 
@JsonSetter(nulls = Nulls.AS_EMPTY)
+                    List<HeaderEntry> userHeadersList) {
         byte[] decodedPayload = Base64.getDecoder().decode(base64Payload);
         Map<HeaderKey, HeaderValue> headersMap = new HashMap<>();
         if (userHeadersList != null) {
@@ -57,51 +52,40 @@ public record Message(
         return of(payload, Collections.emptyMap());
     }
 
-    public static Message of(
-        String payload,
-        Map<HeaderKey, HeaderValue> userHeaders
-    ) {
+    public static Message of(String payload, Map<HeaderKey, HeaderValue> 
userHeaders) {
         final byte[] payloadBytes = payload.getBytes();
         final long userHeadersLength = getUserHeadersSize(userHeaders);
         final MessageHeader msgHeader = new MessageHeader(
-            BigInteger.ZERO,
-            MessageId.serverGenerated(),
-            BigInteger.ZERO,
-            BigInteger.ZERO,
-            BigInteger.ZERO,
-            userHeadersLength,
-            (long) payloadBytes.length
-        );
+                BigInteger.ZERO,
+                MessageId.serverGenerated(),
+                BigInteger.ZERO,
+                BigInteger.ZERO,
+                BigInteger.ZERO,
+                userHeadersLength,
+                (long) payloadBytes.length);
         return new Message(msgHeader, payloadBytes, userHeaders);
     }
 
     public Message withUserHeaders(Map<HeaderKey, HeaderValue> userHeaders) {
-        Map<HeaderKey, HeaderValue> mergedHeaders = mergeUserHeaders(
-            userHeaders
-        );
+        Map<HeaderKey, HeaderValue> mergedHeaders = 
mergeUserHeaders(userHeaders);
         long userHeadersLength = getUserHeadersSize(mergedHeaders);
         MessageHeader updatedHeader = new MessageHeader(
-            header.checksum(),
-            header.id(),
-            header.offset(),
-            header.timestamp(),
-            header.originTimestamp(),
-            userHeadersLength,
-            (long) payload.length
-        );
+                header.checksum(),
+                header.id(),
+                header.offset(),
+                header.timestamp(),
+                header.originTimestamp(),
+                userHeadersLength,
+                (long) payload.length);
         return new Message(updatedHeader, payload, mergedHeaders);
     }
 
     public int getSize() {
         long userHeadersLength = getUserHeadersSize(userHeaders);
-        return Math.toIntExact(
-            MessageHeader.SIZE + payload.length + userHeadersLength
-        );
+        return Math.toIntExact(MessageHeader.SIZE + payload.length + 
userHeadersLength);
     }
 
-    private Map<HeaderKey, HeaderValue> mergeUserHeaders(
-        Map<HeaderKey, HeaderValue> userHeaders
-    ) {
+    private Map<HeaderKey, HeaderValue> mergeUserHeaders(Map<HeaderKey, 
HeaderValue> userHeaders) {
         if (userHeaders.isEmpty()) {
             return this.userHeaders;
         }
@@ -110,16 +94,12 @@ public record Message(
             return userHeaders;
         }
 
-        Map<HeaderKey, HeaderValue> mergedHeaders = new HashMap<>(
-            this.userHeaders
-        );
+        Map<HeaderKey, HeaderValue> mergedHeaders = new 
HashMap<>(this.userHeaders);
         mergedHeaders.putAll(userHeaders);
         return mergedHeaders;
     }
 
-    private static long getUserHeadersSize(
-        Map<HeaderKey, HeaderValue> userHeaders
-    ) {
+    private static long getUserHeadersSize(Map<HeaderKey, HeaderValue> 
userHeaders) {
         if (userHeaders.isEmpty()) {
             return 0L;
         }

Reply via email to