Skip to content

🔧 Output Parsing

Parse composer subcommands' raw text/JSON output into structured Go data — package info, outdated packages, security audit, search results, dependency tree, install/update/remove statistics, self-update, platform requirements, funding, diagnostics, config, version numbers, package name lists.

Many Composer subcommands support --format=json, but the raw JSON shapes vary (some objects, some arrays, some use package names as keys). This module normalizes these heterogeneous outputs into strongly-typed structs, and for several text-only commands (like diagnose, fund, self-update, about) does regex/indentation parsing, so you don't have to hand-write parsing logic.

When to Use

  • 📊 Dashboard / CI reports: convert install / update / outdated / audit output into numeric stats.
  • 🌳 Dependency visualization: ParseDependencyTreeOutput converts composer show --tree tree text into recursively traversable []DependencyNode.
  • 🔍 Retrieval: ParseComposerSearchJSON converts search results into structured entry lists.
  • 🧪 Feed fixed strings in unit tests to assert parse results without real composer calls.
  • 🩺 Self-check: ParseDiagnoseOutputAsChecks splits diagnose's multi-line [OK]/[WARNING]/[ERROR] into per-item checks.

Relationship with Structured Methods

Parse Functions vs Structured Methods

Functions on this page are all package-level functions (Parse*, Extract*), with string input and struct output. They correspond one-to-one with the *Composer methods in audit, packages, version, etc. (like GetAuditInfo, GetOutdatedInfo, GetVersionInfo) — the latter are just syntactic sugar for "first c.Run(...) to get output, then call this page's Parse*". So you can either use the high-level methods or get output yourself and parse manually.

Method Signatures

FunctionSignatureDescription
📦 ParseComposerShowJSONfunc ParseComposerShowJSON(output string) (*PackageInfo, error)Parse show --format=json, equivalent to ParsePackageInfo
🕰️ ParseComposerOutdatedJSONfunc ParseComposerOutdatedJSON(output string) (*OutdatedResult, error)Parse outdated --format=json, equivalent to ParseOutdatedResult
🛡️ ParseComposerAuditJSONfunc ParseComposerAuditJSON(output string) (*AuditInfoResult, error)Parse audit --format=json, equivalent to ParseAuditInfoResult
🔎 ParseComposerSearchJSONfunc ParseComposerSearchJSON(output string) (*SearchResult, error)Parse search --format=json, equivalent to ParseSearchResult
🌳 ParseDependencyTreeOutputfunc ParseDependencyTreeOutput(output string) ([]DependencyNode, error)Parse show --tree text output into dependency tree
🌳 ParseDependencyTreeJSONfunc ParseDependencyTreeJSON(output string) ([]DependencyNode, error)Parse show --tree --format=json dependency tree
⬇️ ParseInstallOutputfunc ParseInstallOutput(output string) *InstallResultParse install output for install/update/remove counts and warnings
🔄 ParseUpdateOutputfunc ParseUpdateOutput(output string) *UpdateResultParse update output for update counts and warnings
➕ ParseRequireOutputfunc ParseRequireOutput(output string, packageName string) *RequireResultParse require output, extract installed version
➖ ParseRemoveOutputfunc ParseRemoveOutput(output string, packageName string) *RemoveResultParse remove output and warnings
⬆️ ParseSelfUpdateOutputfunc ParseSelfUpdateOutput(output string) (oldVersion, newVersion string, err error)Parse self-update output for old/new versions
✅ ParseCheckPlatformReqsOutputfunc ParseCheckPlatformReqsOutput(output string) ([]PlatformRequirement, error)Parse check-platform-reqs text output
💰 ParseFundOutputfunc ParseFundOutput(output string) []FundInfoParse fund text output into funding entry list
🩺 ParseDiagnoseOutputAsChecksfunc ParseDiagnoseOutputAsChecks(output string) []DiagnoseCheckParse diagnose output into check item list
⚙️ ParseConfigOutputfunc ParseConfigOutput(output string) (string, error)Parse config single-value output (whitespace trimmed)
🔢 ExtractVersionFromOutputfunc ExtractVersionFromOutput(output string) (string, bool)Regex extract X.Y.Z version number from any text
📛 ExtractPackageNamesFromOutputfunc ExtractPackageNamesFromOutput(output string) []stringRegex extract vendor/package names from any text (deduplicated)

Structured Return Types

PackageInfo / DependencyNode

ParseComposerShowJSON returns *PackageInfo (fields see packages); ParseDependencyTreeOutput / ParseDependencyTreeJSON return []DependencyNode:

go
type DependencyNode struct {
	Name     string           `json:"name"`
	Version  string           `json:"version,omitempty"`
	Children []DependencyNode `json:"children,omitempty"`
}
FieldTypeDescription
NamestringPackage name, e.g., symfony/console
VersionstringThis node's version (may be empty)
Children[]DependencyNodeRecursive child dependencies

InstallResult / UpdateResult / RequireResult / RemoveResult

go
type InstallResult struct {
	PackagesInstalled int      `json:"packages_installed"`
	PackagesUpdated   int      `json:"packages_updated"`
	PackagesRemoved   int      `json:"packages_removed"`
	Output            string   `json:"output"`
	Warnings          []string `json:"warnings,omitempty"`
}

type UpdateResult struct {
	PackagesUpdated int      `json:"packages_updated"`
	Output          string   `json:"output"`
	Warnings        []string `json:"warnings,omitempty"`
}

type RequireResult struct {
	PackageName string   `json:"package_name"`
	Version     string   `json:"version,omitempty"`
	Output      string   `json:"output"`
	Warnings    []string `json:"warnings,omitempty"`
}

type RemoveResult struct {
	PackageName string   `json:"package_name"`
	Output      string   `json:"output"`
	Warnings    []string `json:"warnings,omitempty"`
}

The Output field retains raw command output for debugging; Warnings collects all lines containing Warning.

PlatformRequirement / FundInfo / DiagnoseCheck

go
type PlatformRequirement struct {
	Package  string `json:"package"`
	Version  string `json:"version,omitempty"`
	Status   string `json:"status"`              // "ok" / "missing" / "mismatch"
	Required string `json:"required,omitempty"`
}

type FundInfo struct {
	Package string `json:"package"`
	Type    string `json:"type,omitempty"`       // "github" / "patreon" / "tidelift", etc.
	URL     string `json:"url,omitempty"`
}

type DiagnoseCheck struct {
	Name   string `json:"name"`
	Status string `json:"status"`                // "ok" / "warning" / "error" / "info"
	Detail string `json:"detail,omitempty"`
}

Examples

Parse outdated JSON Output

go
package main

import (
	"fmt"
	"log"

	"github.com/scagogogo/composer-skills/pkg/composer"
)

func main() {
	comp, err := composer.New(composer.DefaultOptions())
	if err != nil {
		log.Fatal(err)
	}

	// Get raw JSON output of outdated
	output, err := comp.Run("outdated", "--format", "json")
	if err != nil && output == "" {
		// composer may return non-zero exit code when there are no outdated packages, but output still contains valid JSON
		log.Fatalf("Running outdated failed: %v", err)
	}

	// Use parse function to convert JSON to struct
	result, err := composer.ParseComposerOutdatedJSON(output)
	if err != nil {
		log.Fatalf("Failed to parse outdated packages: %v", err)
	}
	for _, pkg := range result.Installed {
		fmt.Printf("%s: installed %s -> upgradeable %s (%s)\n",
			pkg.Name, pkg.Installed, pkg.Latest, pkg.LatestStatus)
	}
	fmt.Printf("Total outdated packages: %d\n", result.Count)
}

Can Also Use High-level Methods

Above uses parse function to parse string directly. If you just want to "run command and get result", use comp.GetOutdatedInfo(), which internally is c.Run("outdated", "--format", "json") + ParseOutdatedResult.

Convert install Output to Stats

go
output := `Loading composer repositories with package information
Updating dependencies
Package operations: 3 installs, 0 updates, 0 removals
  - Installing symfony/console (v5.4.0)
Warning: ...`

result := composer.ParseInstallOutput(output)
fmt.Printf("Installed %d, updated %d, removed %d\n",
	result.PackagesInstalled, result.PackagesUpdated, result.PackagesRemoved)
// Installed 3, updated 0, removed 0
fmt.Printf("Warning count: %d\n", len(result.Warnings))

Parse Dependency Tree Text Output

go
tree := `symfony/console v5.4.0
├── psr/log ~1.0
│   └── ...
└── symfony/polyfill-ctype v1.23.0`

nodes, err := composer.ParseDependencyTreeOutput(tree)
if err != nil {
	log.Fatal(err)
}
for _, root := range nodes {
	fmt.Printf("Root: %s %s, %d child dependencies\n", root.Name, root.Version, len(root.Children))
}

Text vs JSON

ParseDependencyTreeOutput parses composer show --tree indented text (determines level by 4-space indent); ParseDependencyTreeJSON parses --tree --format=json. Both return the same []DependencyNode; choose based on your command invocation.

Parse self-update Output for Old/New Versions

go
output := "Upgrading to 2.6.6 (from 2.6.5)..."
oldVer, newVer, err := composer.ParseSelfUpdateOutput(output)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Upgraded from %s to %s\n", oldVer, newVer)
// Upgraded from 2.6.5 to 2.6.6

ParseSelfUpdateOutput supports three formats: Upgrading to X (from Y), You are already using composer version X, Successfully updated to X.

Extract Version and Package Names from Arbitrary Output

go
text := "Detected symfony/console at version 5.4.0 in vendor/bin"

if ver, ok := composer.ExtractVersionFromOutput(text); ok {
	fmt.Println("Version:", ver) // Version: 5.4.0
}

for _, name := range composer.ExtractPackageNamesFromOutput(text) {
	fmt.Println("Package name:", name) // Package name: symfony/console
}

ExtractVersionFromOutput uses regex (\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?) to match semantic version numbers (including pre-release suffix). ExtractPackageNamesFromOutput matches vendor/package pattern and deduplicates.

Parse diagnose into Per-item Checks

go
output := `[OK] Checking composer version
[OK] Checking platform settings
[WARNING] Checking git settings
[ERROR] Checking http connectivity`

checks := composer.ParseDiagnoseOutputAsChecks(output)
for _, c := range checks {
	fmt.Printf("[%s] %s\n", c.Status, c.Name)
}
// [ok] Checking composer version
// [ok] Checking platform settings
// [warning] Checking git settings
// [error] Checking http connectivity

Advanced

Don't Confuse the Two FundInfo Types

FundInfo returned by ParseFundOutput (result_types.go, contains Package / Type / URL) comes from line-by-line parsing of fund text output; while FundingInfo on the fund page (fund.go, contains URLs slice) comes from --format=json. The two have different fields; choose based on output form.

Parseable Even on Error Exit Codes

composer outdated / audit / validate often return non-zero exit codes when issues are found, but stdout still contains valid JSON. The corresponding high-level methods (GetOutdatedInfo, etc.) handle this and continue parsing; if you directly use the Parse* functions on this page, ensure the output you pass is the actual stdout content, not err.Error().

DependencyNode Text Parsing Indentation Rules

ParseDependencyTreeOutput treats leading , |, `, - as indentation characters, with every 4 indentation characters counting as one level. So it's compatible with Composer's default tree rendering (├── / └── prefixes), but if you customize the output format you may need to switch to JSON parsing.

Released under the MIT License