---
title: グループ化・繰り返しを行ったコンテンツ項目の制御
description: Kurocoでは、コンテンツ定義においてグループ化や繰り返しの設定を行うことで、柔軟なコンテンツ管理が可能です。本ドキュメントでは、グループ化や繰り返しを用いたコンテンツをAPIで扱う際に、レスポンスがどのように変化するのか、また更新時にどのような形式でリクエストを送信すればよいのかについて解説します。
---

Kurocoでは、コンテンツ定義においてグループ化や繰り返しの設定を行うことで、柔軟なコンテンツ管理が可能です。  
本ドキュメントでは、グループ化や繰り返しを用いたコンテンツをAPIで扱う際に、レスポンスがどのように変化するのか、また更新時にどのような形式でリクエストを送信すればよいのかについて解説します。

## APIレスポンス構造

`Topics::list` や `Topics::details` のエンドポイントでデータを取得する場合のレスポンス構造を説明します。

### 繰り返し
項目に繰り返しを設定すると設定した値が配列でレスポンスされます。  
繰り返しの途中のデータを削除した場合は配列の前方に詰められ、空のデータは含まれません。

```json
    "repeat_texts": [
      "text1",
      "text2",
      "text3"
    ],
```

### グループ化
項目をグループ化した場合、`ext_group`のパラメータを有効にしているか否かでレスポンスの形式が異なります。

**ext_group=trueの場合**  
グループ化された項目が1つのオブジェクトにまとまります。  
オブジェクトの項目名に対して管理画面でslugの設定が可能です。  

```json
   "groups": {
      "choice": {
        "key": "key1",
        "label": "value1"
      },
      "image": {
        "id": "2740_ext_04_0",
        "url": "https://xxxxxx.g.kuroco-img.app/v=1747392576/files/topics/2740_ext_4_0.png",
        "desc": "",
        "url_org": "https://xxxxxx.g.kuroco-img.app/files/topics/2740_ext_4_0.png"
      },
      "text": "text"
    },
```

**ext_group=falseの場合**  
それぞれのAPIのレスポンスとなり、レスポンス上はグループ化しない場合と変わりません。

```json
    "choice": {
      "key": "key1",
      "label": "value1"
    },
    "image": {
      "id": "2740_ext_04_0",
      "url": "https://xxxxxx.g.kuroco-img.app/v=1747392576/files/topics/2740_ext_4_0.png",
      "desc": "",
      "url_org": "https://xxxxxx.g.kuroco-img.app/files/topics/2740_ext_4_0.png"
    },
    "text": "text",
```

### 繰り返し+グループ化

**ext_group=trueの場合**  
グループ化されたオブジェクトが配列でレスポンスされます。

```json
    "groups": [
      {
        "choice": {
          "key": "key1",
          "label": "value1"
        },
        "image": {
          "id": "2740_ext_07_0",
          "url": "https://xxxxxx.g.kuroco-img.app/v=1747392576/files/topics/2740_ext_7_0.png",
          "desc": "",
          "url_org": "https://xxxxxx.g.kuroco-img.app/files/topics/2740_ext_7_0.png"
        },
        "text": "text1"
      },
      {
        "choice": {
          "key": "key2",
          "label": "value2"
        },
        "image": {
          "id": "2740_ext_07_1",
          "url": "https://xxxxxx.g.kuroco-img.app/v=1747392576/files/topics/2740_ext_7_1.png",
          "desc": "",
          "url_org": "https://xxxxxx.g.kuroco-img.app/files/topics/2740_ext_7_1.png"
        },
        "text": "text2"
      }
    ],
```

**ext_group=falseの場合**  
それぞれのAPIのレスポンスが配列で返ります。  
グループ化の一部に空のデータがある場合は`""`や`{}`が配列に含まれ、配列のデータ数はグループ化された各項目で同じになります。

```json
    "choice": [
      {
        "key": "key1",
        "label": "value1"
      },
      {
        "key": "key2",
        "label": "value2"
      }
    ],
    "image": [
      {
        "id": "2740_ext_07_0",
        "url": "https://xxxxxx.g.kuroco-img.app/v=1747392576/files/topics/2740_ext_7_0.png",
        "desc": "",
        "url_org": "https://xxxxxx.g.kuroco-img.app/files/topics/2740_ext_7_0.png"
      },
      {
        "id": "2740_ext_07_1",
        "url": "https://xxxxxx.g.kuroco-img.app/v=1747392576/files/topics/2740_ext_7_1.png",
        "desc": "",
        "url_org": "https://xxxxxx.g.kuroco-img.app/files/topics/2740_ext_7_1.png"
      }
    ],
    "text": [
      "",
      "text2"
    ],
```

## APIによる更新

`Topics::update` や `Topics::bulk_upsert` のエンドポイントでデータを更新する場合、基本的には`Topics::details`で取得したレスポンスと同じ構造でリクエストをしますが、グループ化や繰り返しの設定がされた項目を更新する場合には以下の注意点があります。

- グループ化された項目群は全ての項目をPOSTする必要があります。
- 変更しない項目は変更前と同じ値をPOSTしてください。
- 画像の項目は`id`と`desc`の項目のみPOSTします。(`desc`は省略可)

以下にグループ化+繰り返しをした項目を更新する場合の事例を紹介しますので参考にしてください。  
ext_group=trueを設定した`Topoics::update`のエンドポイントを利用する想定で書かれています。

### 一部のデータを差し替える

一部のデータを差し替える場合は`Topics::details`で取得したレスポンスを元に変更したい項目を書き換えてPOSTします。

```json
{
  "text_group": [
    {
      "text_1": "text1-1",      //既存のデータと同一の値をPOST
      "text_2": "New text"      //任意の値をPOST
    },
    {
      "text_1": "text2-1",      //既存のデータと同一の値をPOST
      "text_2": "text2-2"       //既存のデータと同一の値をPOST
    }
  ]
}
```

#### NG例
グループ化された項目群は全項目POSTする必要があります。
以下のように一部の項目を除外し項目数に差が出る場合、データの並び順が不正になることがありますのでご注意ください。

```json
{
  "text_group": [
    {
      "text_1": "text1-1",      //既存のデータと同一の値をPOST
                                //text_2を含めない
    },
    {
      "text_1": "text2-1",      //既存のデータと同一の値をPOST
      "text_2": "text2-2"       //既存のデータと同一の値をPOST
    }
  ]
}
```

### 一部の画像を差し替える

画像の差替えを行いたい場合は、アップロードしたいファイルを `Files::upload` のエンドポイントでKurocoの一時領域にアップロードし、取得した`file_id`をリクエストボディに追加します。

```json
{
  "groups": [
    {
      "choice": {
        "key": "key1",
        "label": "value1"
      },
      "image": {
        "id": "2740_ext_07_0",
        "desc": "test image1"
      },
      "text": "text1"
    },
    {
      "choice": {
        "key": "key2",
        "label": "value2"
      },
      "image": {
        "id": "2740_ext_07_1",
        "file_id": "files/temp/6217dfe10e096f03dce0dc2a60df8240785d5b13880d72477f18c0ff71597070.png",  //差し替えるファイル
        "desc": "test image2"
      },
      "text": "text2"
    }
  ]
}
```

<!--以下はPOSTに含まれない画像"id": "2740_ext_07_0",が消え、データが壊れるので利用不可-->
<!--
画像に対して振られたidを指定して更新する方法

```json
{
  "repeat_groups": [
    {
      "r_image": {
        "id": "2740_ext_07_1",
        "file_id": "files/temp/985a12e67d73c9fc91be443ebf87ea0287f64f2708a70bb46ca56efe57dd0453.png",
        "desc": "test image2"
      }
    }
  ]
}
```
-->

### 並び順を変える

並び順を変える場合は `Topics::details`で取得したレスポンスを元にグループ単位で順番を変えてPOSTします。

```json
{
  "repeat_groups": [
    {
      "r_choice": {
        "key": "key2",
        "label": "value2"
      },
      "r_image": {
        "id": "2740_ext_07_1",
        "desc": "test image2"
      },
      "r_text": "text2"
    },
    {
      "r_choice": {
        "key": "key1",
        "label": "value1"
      },
      "r_image": {
        "id": "2740_ext_07_0",
        "desc": "test image1"
      },
      "r_text": "text1"
    }
  ]
}
```
#### NG例
グループに複数の画像が含まれる場合、一部だけ入れ替える事はできません。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/2f7c5b8939111f8b5ad1e5094cd09ebf.png)

`Topics::update`へのリクエストボディの例で言うと以下の例などです。  

```json
{
  "repeat_multi_image": [
    {
      "image1": {
        "id": "2740_ext_09_1"
      },
      "image2": {
        "id": "2740_ext_10_0"
      }
    },
    {
      "image1": {
        "id": "2740_ext_09_0"
      },
      "image2": {
        "id": "2740_ext_10_1"
      }
    }
  ]
}
```

グループ内で複数のindex番号(_X)が混在することはできませんので、一部の画像を別のグループと入れ替えたい場合は、画像の差し替えをしてください。

### 繰り返しの一部を削除する

繰り返しの一部を削除するには、以下の2通りの方法があります。  

#### 全項目を明示的に空でPOSTする

以下のように、グループ内のすべての項目を空値（`""` や `{}`）でPOSTすることで、グループの削除が可能です。  
項目名は省略せず、すべて含めてPOSTしてください。

```json
{
  "groups": [
    {
      "choice": {},
      "image": {},
      "text": ""
    },
    {
      "choice": {
        "key": "key2",
        "label": "value2"
      },
      "image": {
        "id": "2740_ext_07_0",
        "desc": "test image2"
      },
      "text": "text2"
    }
  ]
}
```

:::caution
グループに真偽値が含まれる場合、真偽値は`""`や`null`での更新を受け付けないため本方法は使用できません。
:::

#### 必要な繰り返し項目のみPOSTする

削除対象となるグループ（オブジェクト）を含めず、登録対象のグループのみをリクエストに含めるようにPOSTしてください。

```json
{
  "groups": [
    {
      "choice": {
        "key": "key2",
        "label": "value2"
      },
      "image": {
        "id": "2740_ext_07_0",
        "desc": "test image2"
      },
      "text": "text2"
    }
  ]
}
```
