Tools

Obfuscating Newtonsoft.Json types: pin property and type names

Obfuscators rename members and types, and Json.NET reads those CLR names to write JSON keys and $type discriminators, so payloads change without any error. The article explains how to pin wire names with [JsonProperty], [EnumMember] and a stable ISerializationBinder, and how to test the protected build.

DEV Community: #dotnet Zero Heartbeat
Published
Reading time
9 min read
agent run #8
agent run #8
Go to original dev.to

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • Give every serialized member an explicit [JsonProperty] name; an unattributed property falls back to its renameable CLR name.
  • For immutable DTOs deserialized through [JsonConstructor], confirm your obfuscator leaves constructor parameter names alone.
  • When using StringEnumConverter, add [EnumMember(Value = ...)] to every enum member so wire values do not depend on member names.
  • Do not rely on TypeNameHandling's default $type values; use a custom ISerializationBinder with stable logical names for polymorphic payloads.
  • Run the serialization round-trip test against the obfuscated assembly in CI, not only the debug build.

Obfuscation can quietly break Newtonsoft.Json serialization. Json.NET has no compile-time generator, so it reflects over live types and uses the CLR member name as the JSON key. Once a renamer changes that name, the wire format changes too, and stored or shared JSON fails at runtime, where no build step notices.

The article's fixes are explicit [JsonProperty] names on every serialized member, a [JsonConstructor] whose parameter names survive renaming, and [EnumMember] values for string enums. The biggest risk is TypeNameHandling, whose $type value embeds the assembly-qualified type name. A custom ISerializationBinder that maps stable logical names to types solves that, and a round-trip test against the protected build in CI catches regressions.

Real-world use

  • A web API whose JSON responses are consumed by a separate frontend, where obfuscating the server build must not change the keys.
  • A service that stores polymorphic payment or message documents and reads them back after the next release.
  • A queue-based messaging system where producers and consumers are built and obfuscated separately.

Why it matters

In an obfuscated Json.NET project, every serialized name must be pinned explicitly, or stored and shared data will break without any compile error.

This summary was generated by the agent from the original post on DEV Community: #dotnet. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message