phpserialize

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 6 Imported by: 0

README

go-phpserialize

A Go library for serializing and deserializing the PHP serialize() / unserialize() data format. The public API mirrors the standard library's encoding/json.

Example:

package main

import (
	"fmt"

	"github.com/justkeval/go-phpserialize"
)

func main() {
	ser, err := phpserialize.Marshal(map[string]any{
		"test":   "value",
		"field2": []int{1, 2, 3, 4, 10},
		"third":  1290,
		"yon":    127.012,
		"nested": map[int]any{
			1: "hell yeah",
			16: struct {
				Field string `php:"tag_field"`
			}{Field: "struct field"},
		},
		"ignored": "ignored lmao",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("Serialized:", string(ser))

	var unser struct {
		Test               string  `php:"test"`
		Field2             []int   `php:"field2"`
		DifferentFieldName uint    `php:"third"`
		Yon                float32 `php:"yon"`
		MissingField       int
		Nested             map[int]any `php:"nested"`
	}
	err = phpserialize.Unmarshal(ser, &unser)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Unserilized: %#v", unser)
}

Goals

  • Familiar API and Developer Experience as encoding/json with Marshal()/Unmarshal().
  • Decoding semantics and flexibility of encoding/json (e.g. struct tags, zero value for missing fields, unknown fields ignored). This was the main motivation for creating this lib as I lacked this from other libs.
  • Be as close to performance as encoding/json. The benchmark_test.go file contains simple benchmarking code for comparison against encoding json, we can add more variation in the benchmark itself also.
  • Correctness and edge case handling. Need to handle every case of semantic differences between types of php and go.

Design

The package is split into four independent layers that communicate only through a single intermediate representation, Value:

Go value ──Encode──▶ Value ──Write──▶ PHP bytes
PHP bytes ──Parse──▶ Value ──Decode─▶ Go value
  • Parser (parser.go) turns PHP serialized bytes into a Value. It is a strict recursive-descent parser and never inspects any Go destination type.
  • Writer (writer.go) turns a Value into canonical PHP serialized bytes.
  • Encode (encode.go) turns a Go value into a Value using reflection.
  • Decode (decode.go) turns a Value into a Go value using reflection.

Reflection lives only in the encode/decode layers; the parser and writer operate purely on bytes and Values.

API

func Marshal(v any) ([]byte, error)
func Unmarshal(data []byte, v any) error

func Parse(data []byte) (Value, error)
func Write(v Value) ([]byte, error)

func Encode(v any) (Value, error)
func Decode(v Value, dst any) error

Marshal is Encode followed by Write; Unmarshal is Parse followed by Decode. Use Parse/Write directly when you need access to the intermediate representation — for example to read a PHP object's class name, which Unmarshal discards.

Supported PHP types

N (null), b (bool), i (int), d (double), s (string), a (array) and O (object). Custom serialized objects (C) and references (R/r) are intentionally not supported; encountering them returns ErrUnsupportedType.

Type mapping

Go → PHP (encode)
Go PHP
nil, nil pointer/interface null
bool bool
all int/uint types int
float32/float64 double
string string
[]byte string (raw bytes)
slice, array sequential array (keys 0..n-1)
map array (keys sorted for determinism)
struct associative array, or object if it implements PHPClass
pointer, interface the value they point to

A struct becomes a PHP object when its type implements:

type PHPClass interface {
    PHPClassName() string
}
PHP → Go (decode into any)
PHP Go
null nil
bool bool
int int64
double float64
string string
sequential array (keys 0..n-1) []any
associative/mixed array map[any]any
object map[string]any (class name discarded)

Decoding into concrete types works as expected: arrays into slices/arrays/maps/structs, objects into structs/maps, with safe numeric conversions and overflow checking.

Struct tags

Struct tags follow encoding/json conventions under the php key:

type T struct {
    Name  string `php:"name"`
    Email string `php:"email,omitempty"`
    Internal int `php:"-"`
}

Float formatting

Doubles are formatted exactly as PHP's serialize() does with the default serialize_precision = -1: the shortest decimal string that round-trips, laid out by PHP's php_gcvt algorithm (including INF, -INF and NAN).

Documentation

Overview

Package phpserialize implements serialization and deserialization of the PHP serialize() data format.

The package is organized into four independent layers:

  • Parser (parser.go): PHP serialized bytes -> Value
  • Writer (writer.go): Value -> PHP serialized bytes
  • Encode (encode.go): Go value -> Value (via reflection)
  • Decode (decode.go): Value -> Go value (via reflection)

The Value type is the intermediate representation shared by all four layers. The parser and writer never inspect Go destination types, and the encoder and decoder never touch raw bytes; reflection lives only in the encode and decode layers.

The high-level entry points Marshal and Unmarshal mirror the API of the standard library's encoding/json package.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupportedType = errors.New("phpserialize: unsupported type")

ErrUnsupportedType is returned by the parser when it encounters a PHP serialized type that this package deliberately does not support: custom serialized objects ("C") and references ("R"/"r").

Functions

func Decode

func Decode(v Value, dst any) error

Decode fills the destination pointed to by dst with the contents of the intermediate Value using reflection. It is the only decoding layer that inspects Go types; it never parses raw bytes.

dst must be a non-nil pointer; otherwise an InvalidUnmarshalError is returned. Decoding into an interface value uses the default mapping described on Unmarshal.

func Marshal

func Marshal(v any) ([]byte, error)

Marshal returns the PHP serialized encoding of v.

It is a convenience wrapper that first encodes v into the intermediate Value representation with Encode and then serializes that Value to bytes with Write. See Encode for the Go-to-PHP type mapping.

func Unmarshal

func Unmarshal(data []byte, v any) error

Unmarshal parses the PHP serialized data and stores the result in the value pointed to by v.

It is a convenience wrapper that first parses data into the intermediate Value representation with Parse and then decodes that Value into v with Decode. v must be a non-nil pointer. See Decode for the PHP-to-Go type mapping, including how PHP values are decoded into an empty interface.

func Write

func Write(v Value) ([]byte, error)

Write serializes an intermediate Value into canonical PHP serialized bytes. It is the exact inverse of Parse. String lengths are emitted as byte counts, using the UTF-8 bytes of Go strings verbatim.

Types

type Entry

type Entry struct {
	Key   Value
	Value Value
}

Entry is a single ordered key/value pair within a PHP array.

type Field

type Field struct {
	Name  string
	Value Value
}

Field is a single named property of a PHP object, in serialization order.

type InvalidUnmarshalError

type InvalidUnmarshalError struct {
	Type reflect.Type
}

InvalidUnmarshalError describes an invalid argument passed to Unmarshal or Decode. The argument must be a non-nil pointer.

func (*InvalidUnmarshalError) Error

func (e *InvalidUnmarshalError) Error() string

type Kind

type Kind uint8

Kind identifies the PHP type carried by a Value.

const (
	// NullKind represents the PHP null value ("N;").
	NullKind Kind = iota
	// BoolKind represents a PHP boolean ("b:0;" or "b:1;").
	BoolKind
	// IntKind represents a PHP integer ("i:<n>;").
	IntKind
	// FloatKind represents a PHP double ("d:<n>;").
	FloatKind
	// StringKind represents a PHP string ("s:<len>:\"...\";").
	StringKind
	// ArrayKind represents a PHP array ("a:<n>:{...}").
	ArrayKind
	// ObjectKind represents a PHP object ("O:<len>:\"class\":<n>:{...}").
	ObjectKind
)

The set of PHP types representable by a Value.

func (Kind) String

func (k Kind) String() string

String returns the name of the kind, useful in error messages.

type Object

type Object struct {
	ClassName string
	Fields    []Field
}

Object is the payload of an ObjectKind value. It records the PHP class name and the object's fields in serialization order.

type PHPClass

type PHPClass interface {
	// PHPClassName returns the PHP class name to use when serializing the
	// implementing value as a PHP object.
	PHPClassName() string
}

PHPClass may be implemented by a Go type to control how it is encoded. When a value's type implements PHPClass, Encode serializes it as a PHP object ("O") using the returned class name, rather than as an associative array.

type SyntaxError

type SyntaxError struct {
	Offset int64
	// contains filtered or unexported fields
}

SyntaxError describes malformed PHP serialized input. Offset records the byte position in the input where the error was detected.

func (*SyntaxError) Error

func (e *SyntaxError) Error() string

type UnmarshalTypeError

type UnmarshalTypeError struct {
	// Value is a description of the PHP value ("int", "string", ...).
	Value string
	// Type is the Go type that could not hold the PHP value.
	Type reflect.Type
	// Field is the struct field path being decoded, if any.
	Field string
}

UnmarshalTypeError describes a PHP value that was not appropriate for a value of a specific Go type during decoding.

func (*UnmarshalTypeError) Error

func (e *UnmarshalTypeError) Error() string

type UnsupportedTypeError

type UnsupportedTypeError struct {
	Type reflect.Type
}

UnsupportedTypeError is returned by Encode and Marshal when a Go value of a type that cannot be represented in the PHP serialized format is encountered (for example a channel or function).

func (*UnsupportedTypeError) Error

func (e *UnsupportedTypeError) Error() string

type UnsupportedValueError

type UnsupportedValueError struct {
	Value reflect.Value
	Str   string
}

UnsupportedValueError is returned by Encode and Marshal when a Go value cannot be represented in the PHP serialized format, such as a map with an unusable key type.

func (*UnsupportedValueError) Error

func (e *UnsupportedValueError) Error() string

type Value

type Value struct {
	Kind Kind

	Bool   bool
	Int    int64
	Float  float64
	String string

	Array  []Entry
	Object *Object
}

Value is the intermediate representation of a single PHP value. It is a tagged union: the Kind field selects which of the remaining fields carries meaningful data.

  • NullKind: no payload.
  • BoolKind: Bool.
  • IntKind: Int.
  • FloatKind: Float.
  • StringKind: String.
  • ArrayKind: Array (ordered key/value entries).
  • ObjectKind: Object (class name plus ordered fields).

func Bool

func Bool(b bool) Value

Bool returns a Value representing a PHP boolean.

func Encode

func Encode(v any) (Value, error)

Encode converts a Go value into the intermediate Value representation using reflection. It is the only encoding layer that inspects Go types; the writer operates purely on Value.

The mapping is:

  • nil, nil pointers and nil interfaces -> PHP null.
  • bool -> PHP bool.
  • all integer and unsigned integer types -> PHP int.
  • float32/float64 -> PHP double.
  • string -> PHP string.
  • []byte -> PHP string (raw bytes).
  • slices and arrays -> sequential PHP array (keys 0..n-1).
  • maps -> PHP array keyed by the map keys (keys sorted for determinism).
  • structs -> associative PHP array, or a PHP object if the type implements PHPClass.
  • pointers and interfaces -> the encoding of the value they refer to.

func Float

func Float(f float64) Value

Float returns a Value representing a PHP double.

func Int

func Int(i int64) Value

Int returns a Value representing a PHP integer.

func Null

func Null() Value

Null returns a Value representing PHP null.

func Parse

func Parse(data []byte) (Value, error)

Parse parses PHP serialized bytes into a Value. It performs a strict recursive-descent parse and never inspects any Go destination type.

The entire input must be consumed by a single serialized value; trailing bytes are reported as a SyntaxError.

func String

func String(s string) Value

String returns a Value representing a PHP string.

func (Value) Equal

func (v Value) Equal(other Value) bool

Equal reports whether v and other represent the same PHP value. Two arrays are equal only when their entries match pairwise in order, and two objects only when their class names and ordered fields match.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL