This page provides an overview of the two document formats used by the gobl.ubl library: GOBL JSON and UBL XML. It explains their structural differences, serialization characteristics, and fundamental design philosophies.
The gobl.ubl library acts as a bridge between GOBL's JSON-based internal representation and UBL's XML-based exchange format. Understanding the differences between these formats is essential for working with the conversion system.
Related Pages:
The gobl.ubl library operates with two distinct document formats that serve complementary roles in the electronic invoicing ecosystem:
| Aspect | GOBL Format | UBL Format |
|---|---|---|
| Serialization | JSON | XML |
| Primary Use | Internal representation, data processing, API exchange | International e-invoicing standard, regulatory compliance |
| Document Structure | Two-layer: gobl.Envelope wrapping bill.Invoice | Single-layer: flat Invoice or CreditNote document |
| Metadata Location | Separate head section in envelope | Inline fields like CustomizationID, ProfileID |
| Namespace Model | JSON $schema URLs for type identification | XML namespaces (7 required: cac, cbc, qdt, udt, ccts, UBL root, xsi) |
| Type System | Go structs from github.com/invopop/gobl package | Go structs defined in this package (invoice.go26-97) |
| Versioning | Schema-based (e.g., draft-0) | Fixed at UBL 2.1 (ubl.go26-28) |
| Tax Representation | Supports both tax-inclusive and tax-exclusive pricing | Tax-exclusive only |
| Regime Handling | $regime field specifies tax jurisdiction | Inferred from party tax IDs |
| Extension Mechanism | $addons array for validation rules | CustomizationID for profile-specific rules |
Sources: ubl.go1-28 invoice.go14-97 test/data/parse/peppol/out/nbio-stuck-ubl.json1-22
Title: GOBL vs UBL Document Architecture
The key structural difference is that GOBL separates document metadata (in head) from payload (in doc), while UBL embeds all information in a flat XML document. This affects how identifiers, validation, and versioning are handled.
Sources: ubl.go30-88 ubl.go90-120 invoice.go26-97 test/data/parse/peppol/out/nbio-stuck-ubl.json1-212
GOBL uses a two-layer envelope pattern where metadata and document content are strictly separated. The outer layer is a gobl.Envelope (from the github.com/invopop/gobl package), and the inner layer is a bill.Invoice.
Title: GOBL Envelope and Document Structure
Example JSON Structure:
Key Design Principles:
head) is separate from business data (doc)$schema fields for type identification$regime field explicitly declares the tax jurisdiction$addons array allows attaching validation rules without modifying the core schemadig (digest) ensures document integrity through cryptographic hashingDuring conversion, the ubl.Convert() function calls env.Extract() to retrieve the inner bill.Invoice from the envelope.
Sources: test/data/parse/peppol/out/nbio-stuck-ubl.json1-22 test/data/parse/france-cius/out/b2b-reg.json1-28 ubl.go103-119
For detailed information about envelope fields, UUID generation, and digest algorithms, see GOBL Envelope Structure.
UBL uses a flat XML document structure where all information is embedded in a single root element (Invoice or CreditNote). The Go representation is the Invoice struct (invoice.go26-97), which handles both document types through conditional fields.
Title: UBL XML Document Structure
Example XML Structure:
Key Design Principles:
cbc for basic, cac for aggregate)CustomizationID and ProfileID specify which validation rules applyInvoice struct handles both invoices and credit notes via conditional fieldsxsi:schemaLocation attribute points to XSD schemas for validationDuring parsing, the ubl.Parse() function calls extractRootNamespace() (ubl.go150-166) to determine whether the document is an Invoice or CreditNote based on the root element's namespace.
Sources: invoice.go26-97 test/data/convert/peppol/out/invoice-with-contract-ref.xml1-12 ubl.go150-166
For detailed information about UBL elements, namespace handling, and schema locations, see UBL Invoice Structure.
GOBL documents are serialized as standard JSON with the following characteristics:
Format Properties:
snake_case convention (e.g., issue_date, tax_id)$ indicate schema metadata ($schema, $regime, $addons)"lines": [...], "$addons": [...]"amount": "195.00"Example:
Sources: test/data/parse/peppol/out/nbio-stuck-ubl.json1-212
UBL documents are serialized as XML with namespace-qualified elements:
Format Properties:
IssueDate, TaxTotal)cbc: for basic, cac: for aggregatecurrencyID, schemeID, unitCodecurrencyID attribute: <cbc:Amount currencyID="EUR">195.00</cbc:Amount>ubl.Bytes() (ubl.go168-176)Example:
Sources: test/data/convert/peppol/out/invoice-with-contract-ref.xml1-125 ubl.go168-176
The Bytes function serializes UBL documents to XML with proper formatting:
The function performs these steps:
xml.MarshalIndent(in, "", " ") for readable XML with 2-space indentation<?xml version="1.0" encoding="UTF-8"?>Sources: ubl.go168-176
GOBL documents are always wrapped in an envelope structure. The conversion process extracts the inner document:
Key Operations:
env.Extract() - Retrieves the inner document from the envelopeensureAddons() - Validates and adds required addons from context (e.g., eu-en16931-v2017)RemoveIncludedTaxes() - Converts tax-inclusive amounts to tax-exclusive (UBL requirement)ublInvoice() - Performs the actual document conversionSources: ubl.go90-120 ubl.go122-148
UBL documents include schema location attributes for XML validation:
| Document Type | Schema Location Constant | Value |
|---|---|---|
| Invoice | SchemaLocationInvoice | urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 http://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/UBL-Invoice-2.1.xsd |
| CreditNote | SchemaLocationCrediteNote | urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2 https://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/UBL-CreditNote-2.1.xsd |
These are set in the Invoice struct's SchemaLocation field during conversion. The schema locations enable validators to fetch the appropriate XSD schemas for document validation.
Sources: invoice.go20-24 invoice.go122-148
The library defines a single UBL version constant:
This value is used to populate the UBLVersionID field in generated Invoice documents, ensuring compliance with UBL 2.1 specifications.
Sources: ubl.go26-28
Refresh this wiki