We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Metadata column repeated when exported as csv
Hi I have recently come across a bug when you export data as csv
<environment.-->
*   Operating System:MacOS 10.14
*   Python Version Used: 3.9.5
*   Doccano installed through pip3 install     doccano 

I have created a DocumentClassification project and have imported some json data. 

The json data is in the format of 

```bash
{"text":"The ravioli was excellent" , "hidden":"The FOOD was excellent"} 
```

When these sentences are imported, the "hidden" : "The FOOD was excellent" becomes part of the Metadata. I have quite a few of these sentences and have labelled them with my own labels 

The issue is when I export the dataset as csv, the Metadata column repeats. For example if I have 10 labelled sentences, the Metadata column is repeated 10 times per row of data in excel. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `backend/api/views/download/data.py`
Content:
```
1 from typing import Any, Dict, List
2 
3 
4 class Record:
5 
6     def __init__(self,
7                  id: int,
8                  data: str,
9                  label: List[Any],
10                  user: str,
11                  metadata: Dict[Any, Any]):
12         self.id = id
13         self.data = data
14         self.label = label
15         self.user = user
16         self.metadata = metadata
17 
18     def __str__(self):
19         return f'{self.data}\t{self.label}'
20
```

Path: `backend/api/views/download/writer.py`
Content:
```
1 import abc
2 import csv
3 import itertools
4 import json
5 import os
6 import uuid
7 import zipfile
8 from collections import defaultdict
9 from typing import Dict, Iterable, Iterator, List
10 
11 from .data import Record
12 
13 
14 class BaseWriter:
15 
16     def __init__(self, tmpdir: str):
17         self.tmpdir = tmpdir
18 
19     @abc.abstractmethod
20     def write(self, records: Iterator[Record]) -> str:
21         raise NotImplementedError()
22 
23     def write_zip(self, filenames: Iterable):
24         save_file = '{}.zip'.format(os.path.join(self.tmpdir, str(uuid.uuid4())))
25         with zipfile.ZipFile(save_file, 'w', compression=zipfile.ZIP_DEFLATED) as zf:
26             for file in filenames:
27                 zf.write(filename=file, arcname=os.path.basename(file))
28         return save_file
29 
30 
31 class LineWriter(BaseWriter):
32     extension = 'txt'
33 
34     def write(self, records: Iterator[Record]) -> str:
35         files = {}
36         for record in records:
37             filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')
38             if filename not in files:
39                 f = open(filename, mode='a')
40                 files[filename] = f
41             f = files[filename]
42             line = self.create_line(record)
43             f.write(f'{line}\n')
44         for f in files.values():
45             f.close()
46         save_file = self.write_zip(files)
47         for file in files:
48             os.remove(file)
49         return save_file
50 
51     @abc.abstractmethod
52     def create_line(self, record) -> str:
53         raise NotImplementedError()
54 
55 
56 class CsvWriter(BaseWriter):
57     extension = 'csv'
58 
59     def write(self, records: Iterator[Record]) -> str:
60         writers = {}
61         file_handlers = set()
62         records = list(records)
63         header = self.create_header(records)
64         for record in records:
65             filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')
66             if filename not in writers:
67                 f = open(filename, mode='a', encoding='utf-8')
68                 writer = csv.DictWriter(f, header)
69                 writer.writeheader()
70                 writers[filename] = writer
71                 file_handlers.add(f)
72             writer = writers[filename]
73             line = self.create_line(record)
74             writer.writerow(line)
75 
76         for f in file_handlers:
77             f.close()
78         save_file = self.write_zip(writers)
79         for file in writers:
80             os.remove(file)
81         return save_file
82 
83     def create_line(self, record) -> Dict:
84         return {
85             'id': record.id,
86             'data': record.data,
87             'label': '#'.join(record.label),
88             **record.metadata
89         }
90 
91     def create_header(self, records: List[Record]) -> Iterable[str]:
92         header = ['id', 'data', 'label']
93         header += list(itertools.chain(*[r.metadata.keys() for r in records]))
94         return header
95 
96 
97 class JSONWriter(BaseWriter):
98     extension = 'json'
99 
100     def write(self, records: Iterator[Record]) -> str:
101         writers = {}
102         contents = defaultdict(list)
103         for record in records:
104             filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')
105             if filename not in writers:
106                 f = open(filename, mode='a', encoding='utf-8')
107                 writers[filename] = f
108             line = self.create_line(record)
109             contents[filename].append(line)
110 
111         for filename, f in writers.items():
112             content = contents[filename]
113             json.dump(content, f, ensure_ascii=False)
114             f.close()
115 
116         save_file = self.write_zip(writers)
117         for file in writers:
118             os.remove(file)
119         return save_file
120 
121     def create_line(self, record) -> Dict:
122         return {
123             'id': record.id,
124             'data': record.data,
125             'label': record.label,
126             **record.metadata
127         }
128 
129 
130 class JSONLWriter(LineWriter):
131     extension = 'jsonl'
132 
133     def create_line(self, record):
134         return json.dumps({
135             'id': record.id,
136             'data': record.data,
137             'label': record.label,
138             **record.metadata
139         }, ensure_ascii=False)
140 
141 
142 class FastTextWriter(LineWriter):
143     extension = 'txt'
144 
145     def create_line(self, record):
146         line = [f'__label__{label}' for label in record.label]
147         line.append(record.data)
148         line = ' '.join(line)
149         return line
150
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/backend/api/views/download/data.py b/backend/api/views/download/data.py
--- a/backend/api/views/download/data.py
+++ b/backend/api/views/download/data.py
@@ -1,3 +1,4 @@
+import json
 from typing import Any, Dict, List
 
 
@@ -16,4 +17,10 @@
         self.metadata = metadata
 
     def __str__(self):
-        return f'{self.data}\t{self.label}'
+        return json.dumps({
+            'id': self.id,
+            'data': self.data,
+            'label': self.label,
+            'user': self.user,
+            'metadata': self.metadata
+        })
diff --git a/backend/api/views/download/writer.py b/backend/api/views/download/writer.py
--- a/backend/api/views/download/writer.py
+++ b/backend/api/views/download/writer.py
@@ -90,7 +90,7 @@
 
     def create_header(self, records: List[Record]) -> Iterable[str]:
         header = ['id', 'data', 'label']
-        header += list(itertools.chain(*[r.metadata.keys() for r in records]))
+        header += sorted(set(itertools.chain(*[r.metadata.keys() for r in records])))
         return header

{"golden_diff": "diff --git a/backend/api/views/download/data.py b/backend/api/views/download/data.py\n--- a/backend/api/views/download/data.py\n+++ b/backend/api/views/download/data.py\n@@ -1,3 +1,4 @@\n+import json\n from typing import Any, Dict, List\n \n \n@@ -16,4 +17,10 @@\n         self.metadata = metadata\n \n     def __str__(self):\n-        return f'{self.data}\\t{self.label}'\n+        return json.dumps({\n+            'id': self.id,\n+            'data': self.data,\n+            'label': self.label,\n+            'user': self.user,\n+            'metadata': self.metadata\n+        })\ndiff --git a/backend/api/views/download/writer.py b/backend/api/views/download/writer.py\n--- a/backend/api/views/download/writer.py\n+++ b/backend/api/views/download/writer.py\n@@ -90,7 +90,7 @@\n \n     def create_header(self, records: List[Record]) -> Iterable[str]:\n         header = ['id', 'data', 'label']\n-        header += list(itertools.chain(*[r.metadata.keys() for r in records]))\n+        header += sorted(set(itertools.chain(*[r.metadata.keys() for r in records])))\n         return header\n", "issue": "Metadata column repeated when exported as csv\nHi I have recently come across a bug when you export data as csv\r\n<environment.-->\r\n*\u00a0\u00a0 Operating System:MacOS 10.14\r\n*\u00a0\u00a0 Python Version Used: 3.9.5\r\n*\u00a0\u00a0 Doccano installed through pip3 install\u00a0\u00a0\u00a0\u00a0 doccano \r\n\r\nI have created a DocumentClassification project and have imported some json data. \r\n\r\nThe json data is in the format of \r\n\r\n```bash\r\n{\"text\":\"The ravioli was excellent\" , \"hidden\":\"The FOOD was excellent\"} \r\n```\r\n\r\nWhen these sentences are imported, the \"hidden\" : \"The FOOD was excellent\" becomes part of the Metadata. I have quite a few of these sentences and have labelled them with my own labels \r\n\r\nThe issue is when I export the dataset as csv, the Metadata column repeats. For example if I have 10 labelled sentences, the Metadata column is repeated 10 times per row of data in excel. \n", "before_files": [{"content": "from typing import Any, Dict, List\n\n\nclass Record:\n\n    def __init__(self,\n                 id: int,\n                 data: str,\n                 label: List[Any],\n                 user: str,\n                 metadata: Dict[Any, Any]):\n        self.id = id\n        self.data = data\n        self.label = label\n        self.user = user\n        self.metadata = metadata\n\n    def __str__(self):\n        return f'{self.data}\\t{self.label}'\n", "path": "backend/api/views/download/data.py"}, {"content": "import abc\nimport csv\nimport itertools\nimport json\nimport os\nimport uuid\nimport zipfile\nfrom collections import defaultdict\nfrom typing import Dict, Iterable, Iterator, List\n\nfrom .data import Record\n\n\nclass BaseWriter:\n\n    def __init__(self, tmpdir: str):\n        self.tmpdir = tmpdir\n\n    @abc.abstractmethod\n    def write(self, records: Iterator[Record]) -> str:\n        raise NotImplementedError()\n\n    def write_zip(self, filenames: Iterable):\n        save_file = '{}.zip'.format(os.path.join(self.tmpdir, str(uuid.uuid4())))\n        with zipfile.ZipFile(save_file, 'w', compression=zipfile.ZIP_DEFLATED) as zf:\n            for file in filenames:\n                zf.write(filename=file, arcname=os.path.basename(file))\n        return save_file\n\n\nclass LineWriter(BaseWriter):\n    extension = 'txt'\n\n    def write(self, records: Iterator[Record]) -> str:\n        files = {}\n        for record in records:\n            filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')\n            if filename not in files:\n                f = open(filename, mode='a')\n                files[filename] = f\n            f = files[filename]\n            line = self.create_line(record)\n            f.write(f'{line}\\n')\n        for f in files.values():\n            f.close()\n        save_file = self.write_zip(files)\n        for file in files:\n            os.remove(file)\n        return save_file\n\n    @abc.abstractmethod\n    def create_line(self, record) -> str:\n        raise NotImplementedError()\n\n\nclass CsvWriter(BaseWriter):\n    extension = 'csv'\n\n    def write(self, records: Iterator[Record]) -> str:\n        writers = {}\n        file_handlers = set()\n        records = list(records)\n        header = self.create_header(records)\n        for record in records:\n            filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')\n            if filename not in writers:\n                f = open(filename, mode='a', encoding='utf-8')\n                writer = csv.DictWriter(f, header)\n                writer.writeheader()\n                writers[filename] = writer\n                file_handlers.add(f)\n            writer = writers[filename]\n            line = self.create_line(record)\n            writer.writerow(line)\n\n        for f in file_handlers:\n            f.close()\n        save_file = self.write_zip(writers)\n        for file in writers:\n            os.remove(file)\n        return save_file\n\n    def create_line(self, record) -> Dict:\n        return {\n            'id': record.id,\n            'data': record.data,\n            'label': '#'.join(record.label),\n            **record.metadata\n        }\n\n    def create_header(self, records: List[Record]) -> Iterable[str]:\n        header = ['id', 'data', 'label']\n        header += list(itertools.chain(*[r.metadata.keys() for r in records]))\n        return header\n\n\nclass JSONWriter(BaseWriter):\n    extension = 'json'\n\n    def write(self, records: Iterator[Record]) -> str:\n        writers = {}\n        contents = defaultdict(list)\n        for record in records:\n            filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')\n            if filename not in writers:\n                f = open(filename, mode='a', encoding='utf-8')\n                writers[filename] = f\n            line = self.create_line(record)\n            contents[filename].append(line)\n\n        for filename, f in writers.items():\n            content = contents[filename]\n            json.dump(content, f, ensure_ascii=False)\n            f.close()\n\n        save_file = self.write_zip(writers)\n        for file in writers:\n            os.remove(file)\n        return save_file\n\n    def create_line(self, record) -> Dict:\n        return {\n            'id': record.id,\n            'data': record.data,\n            'label': record.label,\n            **record.metadata\n        }\n\n\nclass JSONLWriter(LineWriter):\n    extension = 'jsonl'\n\n    def create_line(self, record):\n        return json.dumps({\n            'id': record.id,\n            'data': record.data,\n            'label': record.label,\n            **record.metadata\n        }, ensure_ascii=False)\n\n\nclass FastTextWriter(LineWriter):\n    extension = 'txt'\n\n    def create_line(self, record):\n        line = [f'__label__{label}' for label in record.label]\n        line.append(record.data)\n        line = ' '.join(line)\n        return line\n", "path": "backend/api/views/download/writer.py"}], "after_files": [{"content": "import json\nfrom typing import Any, Dict, List\n\n\nclass Record:\n\n    def __init__(self,\n                 id: int,\n                 data: str,\n                 label: List[Any],\n                 user: str,\n                 metadata: Dict[Any, Any]):\n        self.id = id\n        self.data = data\n        self.label = label\n        self.user = user\n        self.metadata = metadata\n\n    def __str__(self):\n        return json.dumps({\n            'id': self.id,\n            'data': self.data,\n            'label': self.label,\n            'user': self.user,\n            'metadata': self.metadata\n        })\n", "path": "backend/api/views/download/data.py"}, {"content": "import abc\nimport csv\nimport itertools\nimport json\nimport os\nimport uuid\nimport zipfile\nfrom collections import defaultdict\nfrom typing import Dict, Iterable, Iterator, List\n\nfrom .data import Record\n\n\nclass BaseWriter:\n\n    def __init__(self, tmpdir: str):\n        self.tmpdir = tmpdir\n\n    @abc.abstractmethod\n    def write(self, records: Iterator[Record]) -> str:\n        raise NotImplementedError()\n\n    def write_zip(self, filenames: Iterable):\n        save_file = '{}.zip'.format(os.path.join(self.tmpdir, str(uuid.uuid4())))\n        with zipfile.ZipFile(save_file, 'w', compression=zipfile.ZIP_DEFLATED) as zf:\n            for file in filenames:\n                zf.write(filename=file, arcname=os.path.basename(file))\n        return save_file\n\n\nclass LineWriter(BaseWriter):\n    extension = 'txt'\n\n    def write(self, records: Iterator[Record]) -> str:\n        files = {}\n        for record in records:\n            filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')\n            if filename not in files:\n                f = open(filename, mode='a')\n                files[filename] = f\n            f = files[filename]\n            line = self.create_line(record)\n            f.write(f'{line}\\n')\n        for f in files.values():\n            f.close()\n        save_file = self.write_zip(files)\n        for file in files:\n            os.remove(file)\n        return save_file\n\n    @abc.abstractmethod\n    def create_line(self, record) -> str:\n        raise NotImplementedError()\n\n\nclass CsvWriter(BaseWriter):\n    extension = 'csv'\n\n    def write(self, records: Iterator[Record]) -> str:\n        writers = {}\n        file_handlers = set()\n        records = list(records)\n        header = self.create_header(records)\n        for record in records:\n            filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')\n            if filename not in writers:\n                f = open(filename, mode='a', encoding='utf-8')\n                writer = csv.DictWriter(f, header)\n                writer.writeheader()\n                writers[filename] = writer\n                file_handlers.add(f)\n            writer = writers[filename]\n            line = self.create_line(record)\n            writer.writerow(line)\n\n        for f in file_handlers:\n            f.close()\n        save_file = self.write_zip(writers)\n        for file in writers:\n            os.remove(file)\n        return save_file\n\n    def create_line(self, record) -> Dict:\n        return {\n            'id': record.id,\n            'data': record.data,\n            'label': '#'.join(record.label),\n            **record.metadata\n        }\n\n    def create_header(self, records: List[Record]) -> Iterable[str]:\n        header = ['id', 'data', 'label']\n        header += sorted(set(itertools.chain(*[r.metadata.keys() for r in records])))\n        return header\n\n\nclass JSONWriter(BaseWriter):\n    extension = 'json'\n\n    def write(self, records: Iterator[Record]) -> str:\n        writers = {}\n        contents = defaultdict(list)\n        for record in records:\n            filename = os.path.join(self.tmpdir, f'{record.user}.{self.extension}')\n            if filename not in writers:\n                f = open(filename, mode='a', encoding='utf-8')\n                writers[filename] = f\n            line = self.create_line(record)\n            contents[filename].append(line)\n\n        for filename, f in writers.items():\n            content = contents[filename]\n            json.dump(content, f, ensure_ascii=False)\n            f.close()\n\n        save_file = self.write_zip(writers)\n        for file in writers:\n            os.remove(file)\n        return save_file\n\n    def create_line(self, record) -> Dict:\n        return {\n            'id': record.id,\n            'data': record.data,\n            'label': record.label,\n            **record.metadata\n        }\n\n\nclass JSONLWriter(LineWriter):\n    extension = 'jsonl'\n\n    def create_line(self, record):\n        return json.dumps({\n            'id': record.id,\n            'data': record.data,\n            'label': record.label,\n            **record.metadata\n        }, ensure_ascii=False)\n\n\nclass FastTextWriter(LineWriter):\n    extension = 'txt'\n\n    def create_line(self, record):\n        line = [f'__label__{label}' for label in record.label]\n        line.append(record.data)\n        line = ' '.join(line)\n        return line\n", "path": "backend/api/views/download/writer.py"}]}