Skip to content

Byte arrays with fewer than 10 elements are incorrectly deserialized as integer arrays due to heuristic detection #2959

@PastaPastaPasta

Description

@PastaPastaPasta

Expected Behavior

Short byte arrays (fewer than 10 bytes) should be properly deserialized as Value::Bytes when converting from JSON to Value. For example, a 6-byte array representing a MAC address or a 4-byte IPv4 address should remain as bytes.

Current Behavior

The From for Value implementation uses a heuristic that only treats arrays as byte arrays if they have 10 or more elements and all values are in the range [0, 255]. Arrays with fewer than 10 elements are always converted to Value::Array, even when they represent binary data.

This means:

  • [0xDE, 0xAD, 0xBE, 0xEF] → Value::Array (4 bytes, treated as integers)
  • [1, 2, 3, 4, 5, 6] → Value::Array (6 bytes, MAC address lost)
  • [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] → Value::Bytes (10+ elements triggers heuristic)

Relevant code in packages/rs-platform-value/src/converter/serde_json.rs:221-242:
if len >= 10
&& array.iter().all(|v| {
let Some(int) = v.as_u64() else {
return false;
};
int.le(&u8_max)
})
{
//this is an array of bytes
Self::Bytes(...)
}

The code even acknowledges this with //todo: hacky solution, to fix.

Possible Solution

Remove the heuristic entirely and use explicit type information from the schema/context to determine if an array should be bytes. Options:

  1. Schema-aware conversion: Pass document type property information to the conversion function to know when a field is defined as byteArray: true
  2. Explicit wrapper: Use a different JSON representation for bytes (e.g., base64 string or {"$bytes": [...]})
  3. Conversion context parameter: Add an optional parameter to specify expected types during conversion

Alternatives Considered

  • Lower the threshold: Reducing from 10 to a smaller number (e.g., 1) would fix short byte arrays but would incorrectly convert all small integer arrays to bytes
  • Base64 encoding in JSON: Always represent bytes as base64 strings in JSON (this is already done in TryInto but not consistently used)

Additional Context

The same heuristic is duplicated at lines 267-283 for the From<&JsonValue> implementation and would need to be fixed in both places.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions