JsonImportParser
in package
implements
ImportParserInterface
JSON parser producing an {@see ImportDto} with the same output shape as {@see XmlImportParser}: an element maps to a property, repeatable elements to arrays, texts with `lang` to an object keyed by the language alias, a collection is either a plain array (default mode) or `{"mode": "...", "items": [...]}`. Tri-state: a missing key means untouched, `null` (or `""` for texts) means clear.
The whole file is decoded with json_decode() at once (20 MB limit, unlike XML, which streams
because of its 100 MB limit), but the DTO still fills ImportDto::getProducts() with an
iterator over the decoded array, so that validator and executor stay format independent.
Row numbers for the log: JSON has no rows, so ImportProductDto::$line, ImportVariantDto::$line
and ImportBundleDto::$line carry the 1-based position of the item in its array (products[2]
gives line = 3, a variant at variants[0] gives line = 1), not a global order and not a
real file row. A log row always carries the code too, so two cards with the same variant
position stay distinguishable.
Table of Contents
Interfaces
- ImportParserInterface
- Common interface of the three format parsers; all fill one `ImportDto`, so validator and executor are format-independent. {@see XmlImportParser}, {@see CsvImportParser} and {@see JsonImportParser} implement it; {@see ImportParserFactory} selects the implementation by `ProductImportFormat`.
Constants
- BUNDLE_KEYS : array<string|int, mixed> = ['code', 'id', 'action', 'name', 'longName', 's...
- BUNDLE_SCALAR_KEYS : array<string|int, mixed> = ['activated', 'vat']
- BUNDLE_TEXT_KEYS : array<string|int, mixed> = ['name', 'longName', 'shortDescription', 'descr...
- MAX_BYTES : int = 20 * 1024 * 1024
- Size limit of CSV/JSON (20 MB); a defensive cap here too, because the admin add form checks it earlier.
- PRODUCT_KEYS : array<string|int, mixed> = ['id', 'action', 'name', 'description', 'produc...
- PRODUCT_SCALAR_KEYS : array<string|int, mixed> = ['producer', 'productType', 'activated']
- PRODUCT_TEXT_KEYS : array<string|int, mixed> = ['name', 'description']
- ROOT_KEYS : array<string|int, mixed> = ['version', 'settings', 'products', 'bundles']
- SETTINGS_KEYS : array<string|int, mixed> = ['mode', 'matchBy', 'defaultLang', 'collectionM...
- VARIANT_KEYS : array<string|int, mixed> = ['id', 'action', 'code', 'ean', 'isbn', 'name',...
- VARIANT_SCALAR_KEYS : array<string|int, mixed> = ['code', 'ean', 'isbn', 'weight', 'warranty', '...
- VARIANT_TEXT_KEYS : array<string|int, mixed> = ['name', 'longName', 'shortDescription', 'descr...
Methods
- parse() : ImportDto
- buildAccessories() : ImportCollectionDto<string|int, ImportAccessoryDto>|null
- buildBundle() : ImportBundleDto
- buildCategories() : ImportCollectionDto<string|int, ImportCategoryDto>|null
- buildImages() : ImportCollectionDto<string|int, ImportImageDto>|null
- buildParameters() : ImportCollectionDto<string|int, ImportParameterDto>|null
- buildPrices() : array<int, ImportPriceDto>
- buildProduct() : ImportProductDto
- buildSettings() : ImportSettingsDto
- buildStock() : ImportStockDto|null
- buildTags() : ImportCollectionDto<string|int, ImportTagDto>|null
- buildVariant() : ImportVariantDto
- checkUnknownKeys() : void
- readActionKey() : string|null
- readCollectionShape() : array{mode: ?string, items: list}|null
- Recognizes the collection shape: a plain array is the default mode, `{"mode","items"}` is explicit, `null`/`[]` clears (`replace` with empty items; CSV has the same convention with `#NULL`).
- readIntKey() : int|null
- A missing key (or `null`) returns `null`. A present but invalid `id` (negative, 0, decimal, `1e2`, bool, array, non-canonical string, overflow) is not "missing": it logs `KIND_MALFORMED` and returns `null`, and the item is then blocked. Policy: an `int` >= 1 or a canonical digit string ("12") is accepted.
- readLangTexts() : array<int, ImportValue>
- Texts with `lang` as an object keyed by the language alias: `{"cs": "...", "en": "..."}`. The short form, a plain string or `null`, is shorthand for `defaultLang` (the job reads it the same way from `lang=null`, {@see ImportCodebooks::findLanguageId()}).
- readNullableString() : string|null
- readOptionalScalarValue() : ImportValue|null
- readScalarValue() : ImportValue|null
- Tri-state reader: `null`/`""` clears, otherwise the value (bool/number to string).
- yieldProducts() : Generator
Constants
BUNDLE_KEYS
private
array<string|int, mixed>
BUNDLE_KEYS
= ['code', 'id', 'action', 'name', 'longName', 'shortDescription', 'description', 'activated', 'vat', 'tags', 'prices', 'images', 'items']
BUNDLE_SCALAR_KEYS
private
array<string|int, mixed>
BUNDLE_SCALAR_KEYS
= ['activated', 'vat']
BUNDLE_TEXT_KEYS
private
array<string|int, mixed>
BUNDLE_TEXT_KEYS
= ['name', 'longName', 'shortDescription', 'description']
MAX_BYTES
Size limit of CSV/JSON (20 MB); a defensive cap here too, because the admin add form checks it earlier.
private
int
MAX_BYTES
= 20 * 1024 * 1024
PRODUCT_KEYS
private
array<string|int, mixed>
PRODUCT_KEYS
= ['id', 'action', 'name', 'description', 'producer', 'productType', 'activated', 'image', 'categories', 'variants']
PRODUCT_SCALAR_KEYS
private
array<string|int, mixed>
PRODUCT_SCALAR_KEYS
= ['producer', 'productType', 'activated']
PRODUCT_TEXT_KEYS
private
array<string|int, mixed>
PRODUCT_TEXT_KEYS
= ['name', 'description']
ROOT_KEYS
private
array<string|int, mixed>
ROOT_KEYS
= ['version', 'settings', 'products', 'bundles']
allowed keys of the root object.
SETTINGS_KEYS
private
array<string|int, mixed>
SETTINGS_KEYS
= ['mode', 'matchBy', 'defaultLang', 'collectionMode', 'autoCreateProducers', 'autoCreateOptions', 'autoCreateCategories', 'stopOnError']
same set as XmlImportParser::SETTINGS_TAGS.
VARIANT_KEYS
private
array<string|int, mixed>
VARIANT_KEYS
= ['id', 'action', 'code', 'ean', 'isbn', 'name', 'longName', 'shortDescription', 'description', 'unit', 'weight', 'warranty', 'freeDelivery', 'freePayment', 'publishTime', 'unpublishTime', 'activated', 'vat', 'state', 'tags', 'parameters', 'prices', 'stock', 'images', 'accessories']
VARIANT_SCALAR_KEYS
private
array<string|int, mixed>
VARIANT_SCALAR_KEYS
= ['code', 'ean', 'isbn', 'weight', 'warranty', 'freeDelivery', 'freePayment', 'publishTime', 'unpublishTime', 'activated', 'vat', 'state']
VARIANT_TEXT_KEYS
private
array<string|int, mixed>
VARIANT_TEXT_KEYS
= ['name', 'longName', 'shortDescription', 'description']
Methods
parse()
public
parse(string $absolutePath[, string|null $schemaPath = null ]) : ImportDto
Parameters
- $absolutePath : string
-
absolute path to the file (never from the request, always the job
filePath) - $schemaPath : string|null = null
-
optional xsd shape check; only XML supports it, csv/json ignore the parameter
Return values
ImportDtobuildAccessories()
private
buildAccessories(mixed $raw, int $line, array<int, ImportStructureIssueDto> &$issues) : ImportCollectionDto<string|int, ImportAccessoryDto>|null
Parameters
- $raw : mixed
- $line : int
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportCollectionDto<string|int, ImportAccessoryDto>|nullbuildBundle()
private
buildBundle(array<string|int, mixed> $raw, int $line) : ImportBundleDto
Parameters
- $raw : array<string|int, mixed>
- $line : int
Return values
ImportBundleDtobuildCategories()
private
buildCategories(mixed $raw, int $line, array<int, ImportStructureIssueDto> &$issues) : ImportCollectionDto<string|int, ImportCategoryDto>|null
Parameters
- $raw : mixed
- $line : int
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportCollectionDto<string|int, ImportCategoryDto>|nullbuildImages()
private
buildImages(mixed $raw, int $line, array<int, ImportStructureIssueDto> &$issues) : ImportCollectionDto<string|int, ImportImageDto>|null
Parameters
- $raw : mixed
- $line : int
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportCollectionDto<string|int, ImportImageDto>|nullbuildParameters()
private
buildParameters(mixed $raw, int $line, array<int, ImportStructureIssueDto> &$issues) : ImportCollectionDto<string|int, ImportParameterDto>|null
Parameters
- $raw : mixed
- $line : int
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportCollectionDto<string|int, ImportParameterDto>|nullbuildPrices()
private
buildPrices(mixed $raw, int $line, array<int, ImportStructureIssueDto> &$issues) : array<int, ImportPriceDto>
Parameters
- $raw : mixed
- $line : int
- $issues : array<int, ImportStructureIssueDto>
Return values
array<int, ImportPriceDto>buildProduct()
private
buildProduct(array<string|int, mixed> $raw, int $line) : ImportProductDto
Parameters
- $raw : array<string|int, mixed>
- $line : int
Return values
ImportProductDtobuildSettings()
private
buildSettings(array<string|int, mixed> $raw) : ImportSettingsDto
Parameters
- $raw : array<string|int, mixed>
Return values
ImportSettingsDtobuildStock()
private
buildStock(mixed $raw, int $line, array<int, ImportStructureIssueDto> &$issues) : ImportStockDto|null
Parameters
- $raw : mixed
- $line : int
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportStockDto|nullbuildTags()
private
buildTags(mixed $raw, int $line, array<int, ImportStructureIssueDto> &$issues) : ImportCollectionDto<string|int, ImportTagDto>|null
Parameters
- $raw : mixed
- $line : int
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportCollectionDto<string|int, ImportTagDto>|nullbuildVariant()
private
buildVariant(array<string|int, mixed> $raw, int $line) : ImportVariantDto
Parameters
- $raw : array<string|int, mixed>
- $line : int
Return values
ImportVariantDtocheckUnknownKeys()
private
checkUnknownKeys(array<string|int, mixed> $raw, array<int, string> $allowed, string $context, int $line, array<int, ImportStructureIssueDto> &$issues) : void
Parameters
- $raw : array<string|int, mixed>
- $allowed : array<int, string>
- $context : string
- $line : int
- $issues : array<int, ImportStructureIssueDto>
readActionKey()
private
readActionKey(array<string|int, mixed> $raw) : string|null
Parameters
- $raw : array<string|int, mixed>
Return values
string|nullreadCollectionShape()
Recognizes the collection shape: a plain array is the default mode, `{"mode","items"}` is explicit, `null`/`[]` clears (`replace` with empty items; CSV has the same convention with `#NULL`).
private
readCollectionShape(mixed $raw, int $line, string $context, array<int, ImportStructureIssueDto> &$issues) : array{mode: ?string, items: list}|null
Parameters
- $raw : mixed
- $line : int
- $context : string
- $issues : array<int, ImportStructureIssueDto>
Return values
array{mode: ?string, items: list}|null —null when the tag was in the file but has no valid shape (the defect is logged and the section is skipped as if it were missing)
readIntKey()
A missing key (or `null`) returns `null`. A present but invalid `id` (negative, 0, decimal, `1e2`, bool, array, non-canonical string, overflow) is not "missing": it logs `KIND_MALFORMED` and returns `null`, and the item is then blocked. Policy: an `int` >= 1 or a canonical digit string ("12") is accepted.
private
readIntKey(array<string|int, mixed> $raw, string $key, int $line, array<int, ImportStructureIssueDto> &$issues, string $context) : int|null
Parameters
- $raw : array<string|int, mixed>
- $key : string
- $line : int
- $issues : array<int, ImportStructureIssueDto>
- $context : string
Return values
int|nullreadLangTexts()
Texts with `lang` as an object keyed by the language alias: `{"cs": "...", "en": "..."}`. The short form, a plain string or `null`, is shorthand for `defaultLang` (the job reads it the same way from `lang=null`, {@see ImportCodebooks::findLanguageId()}).
private
readLangTexts(mixed $raw, int $line, string $context, array<int, ImportStructureIssueDto> &$issues) : array<int, ImportValue>
Parameters
- $raw : mixed
- $line : int
- $context : string
- $issues : array<int, ImportStructureIssueDto>
Return values
array<int, ImportValue>readNullableString()
private
readNullableString(array<string|int, mixed> $raw, string $key) : string|null
Parameters
- $raw : array<string|int, mixed>
- $key : string
Return values
string|nullreadOptionalScalarValue()
private
readOptionalScalarValue(array<string|int, mixed> $raw, string $key, int $line, string $context, array<int, ImportStructureIssueDto> &$issues) : ImportValue|null
Parameters
- $raw : array<string|int, mixed>
- $key : string
- $line : int
- $context : string
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportValue|nullreadScalarValue()
Tri-state reader: `null`/`""` clears, otherwise the value (bool/number to string).
private
readScalarValue(mixed $raw, int $line, string $context, array<int, ImportStructureIssueDto> &$issues) : ImportValue|null
IMPORTANT: an object or array in place of a scalar field is a shape error, not a "clear"
instruction. If an empty ImportValue were returned, {"ean": }} would pass without an error
and the writer would delete the EAN of an otherwise valid update (setEan($nullOut ? null : $raw)).
Four states must stay distinct: field missing (do not touch), null/"" (clear), value
(write), wrong type (reject the item).
Parameters
- $raw : mixed
- $line : int
- $context : string
- $issues : array<int, ImportStructureIssueDto>
Return values
ImportValue|null —null for a wrong type: the field is not written and the issue blocks the item
yieldProducts()
private
yieldProducts(array<int, ImportProductDto> $products) : Generator
Parameters
- $products : array<int, ImportProductDto>