What are the best techniques for streamlining nested objects with Zod.js?

As a newcomer to zod.js, I have found that the DataSchema function is extremely helpful in verifying API data types and simplifying the API response easily.

However, I'm curious if there is a way to streamline the data transformation process for myExpectedData directly within the zod component (without using the array map method)?

Below is a snippet of my code:

const apiUrl = 'https://api.jikan.moe/v4/top/anime';

const DataSchema = z.array(
    z.object({
        mal_id: z.number().nullable(),
        images: z.object({
            jpg: z.object({
                    image_url: z.string().nullable()
                }

            )
        })
    })
)

type DataSchema = z.infer < typeof DataSchema > ;

async function fetchTopAnime() {
    try {
        const response = await axios.get(apiUrl);
        const rawData = response.data
        const AnimeData = DataSchema.parse(rawData.data)

        const myExpectedData = AnimeData.map((el) => {
            return {
                ...el,
                images: el.images.jpg.image_url
            }
        })

        console.log(myExpectedData);
    } catch (error) {
        console.error(`Error fetching data: ${error}`);
    }
}

fetchTopAnime();

Answer №1

If you want to apply transformations to your data, consider using Zod's transform method:

To customize your data post-parsing, utilize the transform method.

const stringToNumber = z.string().transform((val) => val.length);

stringToNumber.parse("string"); // => 6

[...]

In your scenario:

const DataSchema = z.array(
  z.object({
    mal_id: z.number().nullable(),
    images: z
      .object({
        jpg: z.object({
          image_url: z.string().nullable(),
        }),
      })
      .transform((images) => images.jpg.image_url),
  })
)

You may also choose to transform the "item" object in this way:

const DataSchema = z.array(
  z
    .object({
      mal_id: z.number().nullable(),
      images: z.object({
        jpg: z.object({
          image_url: z.string().nullable(),
        }),
      }),
    })
    .transform((item) => ({
      ...item,
      images: item.images.jpg.image_url,
    }))
)

...or even apply transformations at the array level:

const DataSchema = z
  .array(
    z.object({
      mal_id: z.number().nullable(),
      images: z.object({
        jpg: z.object({
          image_url: z.string().nullable(),
        }),
      }),
    })
  )
  .transform((items) =>
    items.map((item) => ({
      ...item,
      images: item.images.jpg.image_url,
    }))
  )

For better clarity, it is recommended to perform transformations close to the relevant fields. The first option tends to be clearer in this regard.

(Alternatively, if there's always a maximum of one image, you could opt for the second option and rename the field from images to something like image:

const DataSchema = z.array(
  z
    .object({
      mal_id: z.number().nullable(),
      images: z.object({
        jpg: z.object({
          image_url: z.string().nullable(),
        }),
      }),
    })
    .transform((item) => ({
      mal_id: item.mal_id,
      image: item.images.jpg.image_url,
    }))
)

Just a little side note.)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error: Unable to use map function on users .. cannot perform mapping on functions

Initially, the map function in my code was working fine. However, suddenly an error started appearing when I included the users.map line. Surprisingly, if I comment out that line, the code works perfectly again. Even more strangely, if I uncomment it, ev ...

Mongoose Alert: Unable to Create Schema Instance

Below is the Schema file that I'm using: const mongoose = require("mongoose"); const ProblemSchema = new mongoose.Schema( { slug: { type: String, required: true, unique: true, }, title: { type: String, ...

JavaScript error message stating that the setAttribute function is null

As a newcomer to JS, I am currently working on creating a task list webpage that allows users to submit projects and create task lists within each project with designated due dates. In order to generate unique ID tags for projects and tasks, I utilized UU ...

The callback function is not being executed in the Ajax request

$(document).ready(function(){ var requestURL = 'http://www.football-data.org/soccerseasons?callback=?'; $.ajax({ type: 'GET', dataType: 'json', url: requestURL, success: function(data){ cons ...

jQuery problem: Unable to access a property that is undefined

After testing my code on JSfiddle, I noticed that it works perfectly. However, when I try to implement it on a webpage with jQuery already loaded in the DOM, I encounter a console error, shown in the screenshot. I am certain that the iframe selector I am ...

What is the best way to access the next-auth session using getStaticPaths and getStaticProps in dynamic routing scenarios?

I am currently working on implementing dynamic routing in a NextJS application. I need to retrieve the token from next-auth in order to make axios requests to an API and fetch data from getReport and getReports (located in /reports.js). However, I am facin ...

React JS simple validator package not functioning properly with post-property date

I am currently utilizing the simple react validator package for form validation in my react JS project. For those interested, you can find the package at this link: https://www.npmjs.com/package/simple-react-validator However, I have encountered an issue w ...

When working with React JS and the react-select library, I am looking to automatically reset the options to their default value once

I am attempting to disable the select list after unchecking the checkbox and resetting the select value back to default, but currently it is retaining the last selected option. I am utilizing React-select for the select and options in this scenario. APP.j ...

Creating an HTML table from an array in an email using PHP

How can I use data collected by Javascript to generate an email in PHP? The array structure in JavaScript is like this: Menu[ item(name,price,multiplier[],ingred), item(name,price,multiplier[],ingred) ] The array Menu[] is dynamically cr ...

Tips on how to patiently wait until the database connection is established and all queries are successfully executed for every database specified in an array

A file containing JSON data with database details needs to execute a series of queries for each database connection. The map function is currently waiting for the database connection. Below is the start function function start() { console.log('func ...

Developing a real-time form that syncs with a MYSQL database for automatic updates

I am currently working on developing a form with multiple drop-down menus. The first dropdown is populated with 'Customer Name' data retrieved from my MYSQL database. Upon selection, the second dropdown menu below it should display the available ...

Tips for adjusting the radio button value similarly to a checkbox in Angular 2 using *ngFor

my checkbox and radio button implementation: <input id="{{k.group_name}}_{{i}}" name="{{k.group_name}}" type="checkbox" class="hide" name="{{k.group_name}}" [value]="m.details" (change)="change($event, m , k.item_ingredient_group_key,false,k.maximum)"& ...

Combine theme configuration options within Material-UI

I am interested in setting up custom theme rules in Material-UI. My goal is to create both light and dark themes and extend them with some shared settings. My initial idea was to store the common settings for the light and dark themes in a separate variab ...

sending properties to dynamically loaded components

I'm struggling with transferring props between children and parent components using Vue Routes. Within my Layout component, I have a wrapper DIV structured like this: <template> <div class="container" v-bind:class="cssClass ...

Executing JQuery asynchronous calls sequentially

Recently delving into the world of Jquery, I've encountered a coding challenge: my code loops through an array and retrieves HTML from an ajax request for each iteration. $.each(arr, function (data) { $.get('/Quote/LoadQuoteItemCost', { ...

Tips on connecting the endpoints of two parallel quadratic Bezier curves that both begin with a MoveTo command

I am currently working on creating a Sankey Diagram from scratch using VueJS and SVG. I have encountered challenges in closing the paths of two parallel quadratic Bezier curve paths from nodes to nodes. For instance, after some additional calculations, I ...

What is the best way to position my Jchartfx area graph below my gridview?

When my page loads, the graph appears like this. It consistently shows up in the top left corner even though it should be positioned underneath the grid view as intended. var chart1; function createGraph(mpy) { if (mpy == undefined) mpy = 12.00; ch ...

Exploring the dynamic changes in user authentication state with Angular Fire subscriptions

At the moment, I have been listening to authentication state changes in my ngOnInit method of my AppComponent: export class AppComponent implements OnInit { constructor(public fireAuth: AngularFireAuth) { } ngOnInit(): void { this.fireAuth.auth ...

What is the best way to increase the value of a variable using jQuery?

As I work on adding dates to a slider, I find myself needing to increment the values with each click. Initially, I start with the year - 2. $('#adddates').click(function() { var year = 2; $("#slider").dateRangeSlider({ bounds: { ...

can you explain the concept of a backing instance in react?

Although the concept of a "backing instance" is frequently mentioned in React documentation, I found it difficult to grasp its meaning. According to the React docs: In order to interact with the browser, you need a reference to a DOM node. By attaching ...