gcanti / io-ts-types

A collection of codecs and combinators for use with io-ts
https://gcanti.github.io/io-ts-types/
MIT License
311 stars 40 forks source link

How to use JsonFromString decoder inside t.type? #158

Closed utrumo closed 3 years ago

utrumo commented 3 years ago

Can anybody help me to understand how to use JsonFromString inside t.type, how to specify json string and expected json content, how to make functions decode and encode working for it?

my code ```TypeScript // yarn add -D io-ts fp-ts io-ts-reporters io-ts-types monocle-ts newtype-ts import { isLeft } from 'fp-ts/lib/Either'; import * as t from 'io-ts'; import reporter from 'io-ts-reporters'; import { DateFromISOString, JsonFromString } from 'io-ts-types'; const ExternalDataValidator = t.type({ id: t.number, date: DateFromISOString, // nestedJson: JsonFromString // <--- this line }); type IExternalDataValidator = t.TypeOf; const parseData = (data: unknown): IExternalDataValidator | null => { const result = ExternalDataValidator.decode(data); if (isLeft(result)) { const message = reporter.report(result).join('\n'); console.log('error', message); return null; } return result.right; }; const dataFromServer: unknown = { id: 1, date: new Date().toISOString(), nestedJson: JSON.stringify({ message: 'someText' }), }; console.log('unknown data from server', dataFromServer); const parseResult = parseData(dataFromServer); if (parseResult) { console.log('parseResult', parseResult); const encodeResult = ExternalDataValidator.encode(parseResult); if (encodeResult) console.log('encodeResult', encodeResult); } ```

There is a link to codesandbox playground with demonstartion of problem: https://codesandbox.io/s/rs914?file=/src/index.ts

When i uncomment 9 line - i have gеt an error: ![JsonFromStringDecoder](https://user-images.githubusercontent.com/22612354/109388142-53f8fc80-7916-11eb-8ff5-1c164b29d118.png)
gcanti commented 3 years ago

JsonFromString goes from string to Json, so you need a decoder which goes from unknown to string and then you can compose them with pipe:

const ExternalDataValidator = t.type({
  id: t.number,
  date: DateFromISOString,
  nestedJson: t.string.pipe(JsonFromString)
})
utrumo commented 3 years ago

@gcanti, thank you! It's works. How can i add type defenition to json content?

gcanti commented 3 years ago

Go on with your pipeline

const ExternalDataValidator = t.type({
  id: t.number,
  date: DateFromISOString,
  nestedJson: t.string.pipe(JsonFromString).pipe(
    t.type({
      message: t.string
    })
  )
})
utrumo commented 3 years ago

@gcanti, thank you. You solved my problem. :)