From 18ebdbb4dd536aa08f48c93eb4842404b406915b Mon Sep 17 00:00:00 2001 From: Eric Scott Date: Mon, 4 May 2026 07:15:29 -0500 Subject: [PATCH] Support csv format for ArrayField --- docs/fields/array.md | 10 ++++++++++ frictionless/fields/__spec__/test_array.py | 13 +++++++++++++ frictionless/fields/array.py | 12 ++++++++++++ 3 files changed, 35 insertions(+) diff --git a/docs/fields/array.md b/docs/fields/array.md index 75d5765e53..cb9ac456fb 100644 --- a/docs/fields/array.md +++ b/docs/fields/array.md @@ -14,6 +14,16 @@ rows = extract(data, schema=Schema(fields=[fields.ArrayField(name='name')])) print(rows) ``` +Use `format="csv"` to read comma-separated array values. + +```python script tabs=Python +from frictionless import Schema, extract, fields + +data = [["name"], ["value1, value2"]] +rows = extract(data, schema=Schema(fields=[fields.ArrayField(name="name", format="csv")])) +print(rows) +``` + ## Reference ```yaml reference diff --git a/frictionless/fields/__spec__/test_array.py b/frictionless/fields/__spec__/test_array.py index ac26d5ce8c..f758b59275 100644 --- a/frictionless/fields/__spec__/test_array.py +++ b/frictionless/fields/__spec__/test_array.py @@ -20,6 +20,12 @@ ("default", 1, None, {}), ("default", "3.14", None, {}), ("default", "", None, {}), + ("csv", "val1,val2", ["val1", "val2"], {}), + ("csv", "val1, val2", ["val1", "val2"], {}), + ("csv", '"val1,val2", val3', ["val1,val2", "val3"], {}), + ("csv", ["val1", "val2"], ["val1", "val2"], {}), + ("csv", ("val1", "val2"), ["val1", "val2"], {}), + ("csv", 1, None, {}), ], ) def test_array_read_cell(format, source, target, options): @@ -40,6 +46,13 @@ def test_array_read_cell_array_item(): assert notes is None +def test_array_read_cell_array_item_csv(): + field = fields.ArrayField(name="name", format="csv", array_item={"type": "integer"}) + cell, notes = field.read_cell("1,2,3") + assert cell == [1, 2, 3] + assert notes is None + + def test_array_read_cell_array_item_type_error(): field = fields.ArrayField(name="name", array_item={"type": "integer"}) cell, notes = field.read_cell('["1", "2", "bad"]') diff --git a/frictionless/fields/array.py b/frictionless/fields/array.py index fb47aa655c..65b91ad765 100644 --- a/frictionless/fields/array.py +++ b/frictionless/fields/array.py @@ -1,5 +1,6 @@ from __future__ import annotations +import csv import json from typing import Any, Dict, Optional @@ -53,6 +54,17 @@ def cell_reader(cell: Any): cell[index] = item_cell return cell, notes + if self.format == "csv": + def csv_cell_reader(cell: Any): + if isinstance(cell, str): + try: + cell = next(csv.reader([cell], skipinitialspace=True)) + except csv.Error: + cell = None + return cell_reader(cell) + + return csv_cell_reader + return cell_reader def create_value_reader(self):