Skip to content

fix: omit null object properties from serialized events - #137

Draft
marandaneto wants to merge 2 commits into
mainfrom
fix/null-property-serialization-sqq3ojkm
Draft

fix: omit null object properties from serialized events#137
marandaneto wants to merge 2 commits into
mainfrom
fix/null-property-serialization-sqq3ojkm

Conversation

@marandaneto

@marandaneto marandaneto commented Sep 9, 2026

Copy link
Copy Markdown
Member

💡 Motivation and Context

Custom event properties currently retain null object members in network payloads and persisted events. This implements the serialization rule in PostHog/sdk-specs#60 without restricting the existing capture inputs.

The shared event serializer now omits null object members recursively, including objects inside arrays. It preserves null array positions, empty objects, other scalar values, and caller-owned inputs. Existing fallback ToString conversion runs once per occurrence, including when it returns null. Generic serialization used for unrelated cache and state data is unchanged. Only the root $exception_list subtree on $exception keeps its existing nullable metadata semantics.

Includes a patch changeset for com.posthog.unity.

💚 How did you test it?

  • Passed 85 selected EventPropertySerializationTests, JsonSerializerTests, FileStorageProviderTests, and PostHogEventTests against the actual runtime sources on .NET 9. Tests inspect event and batch JSON, invoke the real before-send hook through reflection, write and reopen physical event files, load legacy events, and inspect final batch serialization. Queues do not start and have no network transport.
  • Built all runtime sources with C# 9 and netstandard2.1 using the existing Unity stub assemblies, with zero warnings or errors.
  • Passed targeted CSharpier and dotnet format style checks.
  • Isolated committed-branch autoreview reported no findings after merging current main.

Draft validation limits: No Unity Editor/player, IL2CPP, UnityWebRequest, platform-specific storage, or full public SDK initialization testing was performed. The source/stub tests and build do not establish those platform checks. The full local test suite and local public API checker were not run. All 16 hosted checks passed for b206fc756cdc5fee034d2b60ee55b1cc4da0333c, including build/public API, tests, formatting, security, and SDK compliance. Hosted compliance does not establish the native null-policy checks above because the Unity compliance adapter bypasses native serialization.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed. No public API documentation change is needed.
  • No breaking change or entry added to the changelog. A patch changeset describes the serialization fix.

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

The changeset was authored directly in the repository's existing format. No release is requested.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Implemented and validated with Pi using file tools, Git, .NET, CSharpier, the isolated autoreview helper, and GitHub CLI under human direction. The fix stays in the existing event serializer rather than adding a wrapper prepass or changing dependencies. Private session logs are not published. Human review and the native platform checks above remain required.

@marandaneto marandaneto self-assigned this Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

posthog-unity Compliance Report

Date: 2026-09-09 09:33:25 UTC
Duration: 105871ms

✅ All Tests Passed!

46/46 tests passed


Capture Tests

29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields 86ms
Format Validation.Event Has Uuid 11ms
Format Validation.Event Has Lib Properties 9ms
Format Validation.Distinct Id Is String 10ms
Format Validation.Token Is Present 8ms
Format Validation.Custom Properties Preserved 15ms
Format Validation.Event Has Timestamp 9ms
Retry Behavior.Retries On 503 6524ms
Retry Behavior.Does Not Retry On 400 2015ms
Retry Behavior.Does Not Retry On 401 2011ms
Retry Behavior.Respects Retry After Header 8019ms
Retry Behavior.Implements Backoff 18522ms
Retry Behavior.Retries On 500 5517ms
Retry Behavior.Retries On 502 5518ms
Retry Behavior.Retries On 504 5517ms
Retry Behavior.Max Retries Respected 18520ms
Deduplication.Generates Unique Uuids 14ms
Deduplication.Preserves Uuid On Retry 5510ms
Deduplication.Preserves Uuid And Timestamp On Retry 11527ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry 5520ms
Deduplication.No Duplicate Events In Batch 14ms
Deduplication.Different Events Have Different Uuids 9ms
Compression.Sends Gzip When Enabled 10ms
Batch Format.Uses Proper Batch Structure 7ms
Batch Format.Flush With No Events Sends Nothing 4ms
Batch Format.Multiple Events Batched Together 13ms
Error Handling.Does Not Retry On 403 2009ms
Error Handling.Does Not Retry On 413 2011ms
Error Handling.Retries On 408 5516ms

Feature_Flags Tests

17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id 24ms
Request Payload.Flags Request Uses V2 Query Param 7ms
Request Payload.Flags Request Hits Flags Path Not Decide 6ms
Request Payload.Flags Request Omits Authorization Header 6ms
Request Payload.Token In Flags Body Matches Init 5ms
Request Payload.Groups Round Trip 6ms
Request Payload.Groups Default To Empty Object 5ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False 6ms
Request Payload.Disable Geoip Omitted Defaults To False 5ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key 6ms
Request Lifecycle.No Flags Request On Init Alone 2ms
Request Lifecycle.No Flags Request On Normal Capture 7ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests 9ms
Request Lifecycle.Mock Response Value Is Returned To Caller 6ms
Retry Behavior.Retries Flags On 502 508ms
Retry Behavior.Retries Flags On 504 509ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event 9ms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant