<p>I don't think you want to use the <code>Fields::EVENT_BEFORE_PARSE_FIELD</code> event here - that's too late in the process to do what you need. Instead you should fix the property in your input data that you want to map to categories, by preprocessing it into an array. The easiest way to do this in Feed Me is with a <a href="https://docs.craftcms.com/feed-me/v4/developers/data-types.html" rel="nofollow noreferrer">custom Data Type</a>.</p>
<p>All we need to do in this case is extend Feed Me's built-in JSON Data Type and loop over the items in the feed to post process them:</p>
<pre class="lang-php prettyprint-override"><code>&lt;?php

namespace modules\datatypes;

use craft\feedme\datatypes\Json;
use illuminate\Support\Collection;

class CustomJsonDatatype extends Json
{
    /**
     * @var string
     */
    // This will be the name of the Feed Type visible when setting up the feed
    public static string $name = 'Custom JSON';
    
    // Public Methods
    // =========================================================================

    /**
     * @inheritDoc
     */
    public function getFeed($url, $settings, bool $usePrimaryElement = true): array
    {
        // Get the feed from the parent class
        $feed = parent::getFeed($url, $settings, $usePrimaryElement);

        // Map over the data key with our custom transformer method
        $feed['data'] = collect($feed['data'])
            -&gt;map(function($item) {
                return $this-&gt;transformItem(collect($item));
            })
            -&gt;toArray();
        return $feed;
    }
    
    public function transformItem(Collection $item): ?Collection
    {
        // do whatever you want here to each item - the below is untested but _should_ work
        if ($item-&gt;Category) {
            $values = collect(explode('|', $item-&gt;Category));
            $item-&gt;put('Category', $values-&gt;map(fn($value) =&gt; trim($value))-&gt;toArray());
        }
        
        return $item;
    }
}
</code></pre>
<p>Then in a custom module register your Data Type with Feed Me:</p>
<pre class="lang-php prettyprint-override"><code>&lt;?php

namespace modules;

use Craft;
use craft\feedme\events\RegisterFeedMeDataTypesEvent;
use craft\feedme\services\DataTypes;
use modules\datatypes\CustomJsonDatatype;
use yii\base\Event;
use yii\base\Module as BaseModule;

class Module extends BaseModule
{
    public function init(): void
    {
        Craft::setAlias('@modules', __DIR__);

        parent::init();

        Craft::$app-&gt;onInit(function() {
            $this-&gt;registerFeedMeDataTypes();
        });
    }
    
    private function registerFeedMeDataTypes(): void
    {
        // see https://docs.craftcms.com/feed-me/v4/developers/data-types.html#the-registerfeedmedatatypes-event
        Event::on(
            DataTypes::class,
            DataTypes::EVENT_REGISTER_FEED_ME_DATA_TYPES,
            static function(RegisterFeedMeDataTypesEvent $e) {
                $e-&gt;dataTypes[] = CustomJsonDatatype::class;
            }
        );
    }
}
</code></pre>

CC BY-SA 4.0
2023-08-02T13:06:14.193Z
Thank you @Tom Davies, this seems like a very good answer from a very wise man.
John
CC BY-SA 4.0
2023-09-14T13:42:54.077Z
You forgot "handsome"
Tom Davies
CC BY-SA 4.0
2023-08-02T11:11:45.357Z
2023-08-02T11:11:45.357Z
Tom Davies
<p>I've got a json data feed that has related entry titles in a pipe delimited format like so:</p>
<p><code>'Entry1 | Entry2 | Entry3'</code></p>
<p>I thought feedme actually used to be ok with that, but it looks like now it has to be an array.</p>
<p>So i'm trying to hook into a FeedMe event and transform that data into an array before FeedMe then parses it.</p>
<pre><code>Event::on(Fields::class, Fields::EVENT_BEFORE_PARSE_FIELD, function(FieldEvent $event) {
            $value = $event-&gt;parsedValue;
            if ($event-&gt;feed['id'] == 1) {
                if ($event-&gt;fieldHandle === 'category') {
                    $newValue = array_map('trim', explode('|', $value));
                    $event-&gt;parsedValue = $newValue;
                }
            }
        });
</code></pre>
<p>This doesn't seem to be having any effect though, what am I missing?</p>
<p>Thx!</p>

<plugin-feedme>
In FeedMe transform one data element before it gets parsed
# In FeedMe transform one data element before it gets parsed

(Asked by: username_0 on 2023-08-01)

I've got a json data feed that has related entry titles in a pipe delimited format like so:
'Entry1 | Entry2 | Entry3'
I thought feedme actually used to be ok with that, but it looks like now it has to be an array.
So i'm trying to hook into a FeedMe event and transform that data into an array before FeedMe then parses it.
Event::on(Fields::class, Fields::EVENT_BEFORE_PARSE_FIELD, function(FieldEvent $event) {
            $value = $event->parsedValue;
            if ($event->feed['id'] == 1) {
                if ($event->fieldHandle === 'category') {
                    $newValue = array_map('trim', explode('|', $value));
                    $event->parsedValue = $newValue;
                }
            }
        });

This doesn't seem to be having any effect though, what am I missing?
Thx!

**Tags:** plugin-feedme


---

## 1 answers

### Answer by username_1 on 2023-08-02. Score: 3 | Accepted answer

I don't think you want to use the Fields::EVENT_BEFORE_PARSE_FIELD event here - that's too late in the process to do what you need. Instead you should fix the property in your input data that you want to map to categories, by preprocessing it into an array. The easiest way to do this in Feed Me is with a custom Data Type.
All we need to do in this case is extend Feed Me's built-in JSON Data Type and loop over the items in the feed to post process them:
map(function($item) {
                return $this->transformItem(collect($item));
            })
            ->toArray();
        return $feed;
    }
    
    public function transformItem(Collection $item): ?Collection
    {
        // do whatever you want here to each item - the below is untested but _should_ work
        if ($item->Category) {
            $values = collect(explode('|', $item->Category));
            $item->put('Category', $values->map(fn($value) => trim($value))->toArray());
        }
        
        return $item;
    }
}

Then in a custom module register your Data Type with Feed Me:
onInit(function() {
            $this->registerFeedMeDataTypes();
        });
    }
    
    private function registerFeedMeDataTypes(): void
    {
        // see https://docs.craftcms.com/feed-me/v4/developers/data-types.html#the-registerfeedmedatatypes-event
        Event::on(
            DataTypes::class,
            DataTypes::EVENT_REGISTER_FEED_ME_DATA_TYPES,
            static function(RegisterFeedMeDataTypesEvent $e) {
                $e->dataTypes[] = CustomJsonDatatype::class;
            }
        );
    }
}

> **Comments:**
> **username_0**: Thank you @username_1, this seems like a very good answer from a very wise man.  
> **username_1**: You forgot "handsome"  

---

