Document Serialization Approach

Page describes the approach used to serialize the document content to be able to produce hash code that would not be affected during JSON or XML document transfer over the network or affected due to serialization/deserialization on different platforms and using different serialization tools.

Serialization Algorithm

To ensure data transfer over network, potential newline symbols or spaces added removed between XML and JSON elements are not changing the signature value, the solution leverages specialized data document serialization approach to ensure only significant data (names and values of fields) is used as part of the signature.

Algorithm Overview

The algorithm to implement when serializing data to get hash code to sign is:

  1. Documents processed recursively, starting from the root element of the document. See the note below!
  2. All property names are converted to culture invariant uppercase.
  3. All property values are taken without any processing, just like those are in the input document. E.g., if original document has value 0.0, it should be moved to serialized string as 0.0 and cannot be moved as 0 or 0.00.
  4. All property names and simple type values (those, which are not objects) are enclosed into double quotes symbol ".
  5. In JSON – entire array serialization result is prefixed with the array property name and every array element is preceded with the array property name. This is one place, where difference with XML exists, as in XML there would be one prefix for the entire array serialization output and other names for individual elements. E.g.:
    • In JSON we would receive something like “TAXABLEITEMS”“TAXABLEITEMS”<taxable item #1 serialization output>“TAXABLEITEMS”<taxable item #2 serialization output> …
    • While in XML: “TAXABLEITEMS”“TAXABLEITEM”<taxable item #1 serialization output>“TAXABLEITEM”<taxable item #2 serialization output> …
  6. Double quotes " in XML fields are replaced with the escape sequence \” to prevent users from being able to create different documents with same serialization output. This is not needed in JSON as \” is generally the way to store double quotes in the property values there.

As an example, see the document content without signature in XML and JSON and resulting strings that would be produced as a result of data serialization (XML and JSON) before applying SHA256 hashing.

Note!

eInvoicing:

The root of the document is not the root of the entire submission. For XML root of the document is tag. For JSON document root of the document is object delimiter element that encloses all the other document attributes. Root is not the entire documents array of JSON. See examples above showing serialization results for one JSON document and one XML document as well.

eReceipt:

Receipts are grouped into batches. Every batch is processed as one submission. Serialization is applied to the entire batch. Batches in JSON format only, are supported.

The JSON and XML files referenced here are just samples and might not contain the recent documents structure, always refer to the recent documents structure in Egyptian eInvoicing SDK.postman_collection.json (use right-click Save As…)

Pseudo Code Implementation

Implementation for JSON:

function string Serialize(documentStructure)
    
    if documentStructure is simple value type
        return """ + documentStructure.value + """
    end if

    var serializedString = ""
    
    foreach element in the structure:
        
        if element is not array type
            serializeString.Append (""" + element.name.uppercase + """)
            serializeString.Append ( Serialize(element.value) )
        end if

        if element is of array type
            serializeString.Append (""" + element.name.uppercase + """)
            foreach array element in element: 
                // use below line for JSON because subelements of array in JSON do not have own names
                serializeString.Append (""" + element.name.uppercase + """)         
                serializeString.Append ( Serialize(arrayelement.value) )              
            end foreach
        end if

    end foreach

    return serializedString
end function

Implementation for XML:

function string Serialize(documentStructure)
    
    if documentStructure is simple value type
        return """ + EscapeQuotes(documentStructure.value) + """
    end if

    var serializedString = ""
    
    foreach element in the structure:
        
        serializeString.Append (""" + element.name.uppercase + """)
        serializeString.Append ( Serialize(element.value) )

    end foreach

    return serializedString
end function

function string EscapeQuotes(stringValue){
    return Replace(stringValue, """, "\"")
}