Universal.Common.Serialization.Php
1.1.1
dotnet add package Universal.Common.Serialization.Php --version 1.1.1
NuGet\Install-Package Universal.Common.Serialization.Php -Version 1.1.1
<PackageReference Include="Universal.Common.Serialization.Php" Version="1.1.1" />
<PackageVersion Include="Universal.Common.Serialization.Php" Version="1.1.1" />
<PackageReference Include="Universal.Common.Serialization.Php" />
paket add Universal.Common.Serialization.Php --version 1.1.1
#r "nuget: Universal.Common.Serialization.Php, 1.1.1"
#:package Universal.Common.Serialization.Php@1.1.1
#addin nuget:?package=Universal.Common.Serialization.Php&version=1.1.1
#tool nuget:?package=Universal.Common.Serialization.Php&version=1.1.1
Universal.Common.Serialization.Php
A .NET library for deserializing PHP serialized data into .NET objects. Deserialization only - this library focuses on reading PHP serialized data, not writing it.
Note: This library exists to help you escape PHP serialization hell. If you had a choice, I know you would have chosen JSON instead. This library is here to do this one thing well - deserialize PHP data with the same level of quality and performance as System.Text.Json does for JSON.
Scope
- ✅ Deserializes PHP
serialize()output to .NET types - ✅ Handles primitives, arrays, objects, references, and enums
- ✅ Maps PHP arrays/objects to strongly-typed C# classes (most libraries only support dictionaries)
- ✅ Supports constructor parameter binding and property mapping
- ❌ Does not serialize .NET objects to PHP format
- ❌ Does not map PHP class names to C# class names (use property mapping instead)
- ❌ Does not preserve PHP visibility modifiers (public/protected/private)
Quick Start
using Universal.Common.Serialization.Php;
// Recommended: From byte array (most PHP data comes base64-encoded)
byte[] phpData = Convert.FromBase64String("czoxMToiaGVsbG8gd29ybGQiOw==");
string greeting = PhpSerializer.Deserialize<string>(phpData);
// Result: "hello world"
// Deserialize to strongly-typed class
string phpUserData = "a:2:{s:4:\"name\";s:4:\"John\";s:3:\"age\";i:30;}";
var user = PhpSerializer.Deserialize<User>(
phpUserData,
Encoding.UTF8);
// user.Name = "John", user.Age = 30
// Or as a dictionary when structure is unknown
var data = PhpSerializer.Deserialize<Dictionary<string, object>>(
phpUserData,
Encoding.UTF8);
// data["name"] = "John", data["age"] = 30L
Supported Types
Primitives
- Strings:
s:5:"hello";→string - Integers:
i:42;→int,long - Booleans:
b:1;→bool - Doubles:
d:3.14;→double,float - Null:
N;→null
Collections
- PHP arrays →
Dictionary<TKey, TValue>,List<T>,T[],HashSet<T> - Nested arrays supported
Objects
- PHP objects → Custom classes via property mapping
- Supports parameterless constructors and constructor parameter binding
- Case-insensitive property matching (configurable)
Advanced
- References:
r:2;andR:1;(requiresTrackReferences = true) - PHP 8.1+ Enums:
E:25:"Permission:manage"; - DateTime from strings or Unix timestamps
- GUIDs from string representations
Configuration
var options = new PhpSerializerOptions
{
TrackReferences = true, // Handle PHP references
MaxDepth = 64, // Prevent stack overflow
PropertyNameCaseInsensitive = true, // Case-insensitive property matching
DefaultEncoding = Encoding.UTF8, // String encoding (important!)
AllowTrailingData = false, // Reject extra data after valid PHP
IgnoreNullValues = false, // How to handle null values
NumberHandling = PhpNumberHandling.Strict // String-to-number coercion
};
var result = PhpSerializer.Deserialize<MyClass>(data, options);
Custom Converters
public class CustomDateTimeConverter : PhpConverter<DateTime>
{
public override DateTime Read(ref PhpReader reader, Type typeToConvert,
PhpSerializerOptions options, PhpDeserializationContext context)
{
string dateStr = reader.GetString(options.DefaultEncoding);
return DateTime.ParseExact(dateStr, "Y-m-d H:i:s", CultureInfo.InvariantCulture);
}
}
var options = new PhpSerializerOptions();
options.Converters.Add(new CustomDateTimeConverter());
Attributes
public class User
{
// Could also use PhpNamingPolicy.SnakeCaseToPascalCase
[PhpPropertyName("user_id")]
public int UserId { get; set; }
[PhpIgnore]
public string InternalField { get; set; }
[PhpExtensionData]
public Dictionary<string, object> ExtraData { get; set; }
}
Important: String Encoding
PHP strings are byte strings with no inherent encoding. Always specify the encoding used by your PHP application:
// UTF-8 (most common)
PhpSerializer.Deserialize<T>(data, Encoding.UTF8, options);
// Latin-1 (ISO-8859-1)
PhpSerializer.Deserialize<T>(data, Encoding.GetEncoding("ISO-8859-1"), options);
// Windows-1252
PhpSerializer.Deserialize<T>(data, Encoding.GetEncoding("windows-1252"), options);
Wrong encoding = garbage data. When in doubt, ask your PHP developers.
Mapping PHP Property Names
PHP often uses snake_case while C# uses PascalCase. Choose your strategy:
Strategy 1: Attributes (Fine-grained Control)
public class User
{
[PhpPropertyName("user_id")]
public int UserId { get; set; }
[PhpPropertyName("first_name")]
public string FirstName { get; set; }
}
Pros: Explicit, works for one-off mappings
Cons: Verbose if you have many properties
Strategy 2: Naming Policy (Convention-based)
var options = new PhpSerializerOptions
{
PropertyNamingPolicy = PhpNamingPolicy.SnakeCaseToPascalCase
};
var user = PhpSerializer.Deserialize<User>(data, options);
public class User
{
public int UserId { get; set; } // Matches "user_id"
public string FirstName { get; set; } // Matches "first_name"
}
Pros: Clean, works across all types, no attributes needed
Cons: All-or-nothing, can't override individual properties
Strategy 3: Hybrid (Best of Both)
var options = new PhpSerializerOptions
{
PropertyNamingPolicy = PhpNamingPolicy.SnakeCaseToPascalCase
};
public class User
{
public int UserId { get; set; } // Uses naming policy
[PhpPropertyName("legacy_field_name")] // Override for exceptions
public string WeirdField { get; set; }
}
Note: [PhpPropertyName] takes precedence over naming policies.
Error Handling
try
{
var result = PhpSerializer.Deserialize<MyClass>(data);
}
catch (PhpSerializationException ex)
{
// Invalid PHP format, type mismatch, or reference error
Console.WriteLine($"Deserialization failed: {ex.Message}");
}
Thread Safety
PhpSerializerOptionsis thread-safe and can be reusedPhpSerializerstatic methods are thread-safePhpDeserializationContextis per-operation and NOT thread-safe
Limitations
If you need to:
- Serialize .NET objects back to PHP format → Not supported
- Preserve PHP class names so we can round-trip the data → Not our problem
- Handle PHP's
Serializableinterface → Write a custom converter - Deal with recursive references without
TrackReferences→ EnableTrackReferences
Good luck!
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Memory (>= 4.6.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Fixed custom converter precedence.