<p>You could define a union type for values, something like</p>
<pre><code>data Val = B BuiltinByteString
  | M (AssocMap BuiltinByteString Val)

type OrcFax = AssocMap BuiltinByteString Val
</code></pre>
<p>then you can deserialise the <code>Datum</code> to a raw <code>Data</code> and &quot;parse&quot; it manually, pattern matching on the parts you are interested in. <code>Data</code> being a generic description of any data structure, allows to mix types this way.</p>

CC BY-SA 4.0
2023-11-08T07:57:56.900Z
2023-11-08T07:57:56.900Z
insitu
<p>We have a specific Datum, taken from Orcfax oracle UTXO:
<a href="https://preprod.cexplorer.io/datum/9ced750ebbb2c9a9eac2e07a91525cadd3bfab23950089faa3e3a55517d1033f" rel="nofollow noreferrer">https://preprod.cexplorer.io/datum/9ced750ebbb2c9a9eac2e07a91525cadd3bfab23950089faa3e3a55517d1033f</a></p>
<p>the part we are interested in is the very first field, map:</p>
<pre><code>&quot;map&quot;: [
        {
            &quot;k&quot;: {
                &quot;bytes&quot;: &quot;40636f6e74657874&quot;
            },
            &quot;v&quot;: {
                &quot;bytes&quot;: &quot;68747470733a2f2f736368656d612e6f7267&quot;
            }
        },
        {
            &quot;k&quot;: {
                &quot;bytes&quot;: &quot;5f3a636f6e74656e745369676e6174757265&quot;
            },
            &quot;v&quot;: {
                &quot;bytes&quot;: &quot;61346230303130306537313331386533633130373266343332643930373264376530356230386530666338353333656363323531323861623934653737323937&quot;
            }
        },
        {
            &quot;k&quot;: {
                &quot;bytes&quot;: &quot;6964656e746966696572&quot;
            },
            &quot;v&quot;: {
                &quot;map&quot;: [
                    {
                        &quot;k&quot;: {
                            &quot;bytes&quot;: &quot;70726f70657274794944&quot;
                        },
                        &quot;v&quot;: {
                            &quot;bytes&quot;: &quot;41726b6c79204964656e746966696572&quot;
                        }
                    },
                    {
                        &quot;k&quot;: {
                            &quot;bytes&quot;: &quot;74797065&quot;
                        },
                        &quot;v&quot;: {
                            &quot;bytes&quot;: &quot;50726f706572747956616c7565&quot;
                        }
                    },
                    {
                        &quot;k&quot;: {
                            &quot;bytes&quot;: &quot;76616c7565&quot;
                        },
                        &quot;v&quot;: {
                            &quot;bytes&quot;: &quot;75726e3a6f72636661783a61636130373632622d326661372d346461622d396261352d663935333631373430633738&quot;
                        }
                    }
                ]
            }
        },
        {
            &quot;k&quot;: {
                &quot;bytes&quot;: &quot;6e616d65&quot;
            },
            &quot;v&quot;: {
                &quot;bytes&quot;: &quot;4144412d5553447c5553442d414441&quot;
            }
        },
        .........................
</code></pre>
<p>The strange thing is, values are of a different type. Some are strings, some are lists or integers. As far as I understand, in Plutus/Haskell, AssocMap can contain only values of the same type, and there is no way to declare a type for this Map.</p>
<p>The closest I get to this structure in Plutus is this:</p>
<pre><code>import PlutusTx.AssocMap (Map, fromList)

data OrcfaxDatum = OrcfaxDatum {
    testOne  :: BuiltinByteString,
    testTwo  :: (Map BuiltinByteString BuiltinByteString, Map BuiltinByteString Integer, Map BuiltinByteString [Integer])
  } deriving Show
PlutusTx.makeIsDataIndexed ''OrcfaxDatum [('OrcfaxDatum, 0)]
PlutusTx.makeLift ''OrcfaxDatum

-- in offchain code:
let datum = OrcfaxDatum &quot;test&quot; (fromList [(&quot;test&quot;, &quot;test&quot;)], fromList [(&quot;test&quot;, 1)], fromList [(&quot;test&quot;, [1])])
let dr = encode (scriptDataToJson ScriptDataJsonDetailedSchema $ fromPlutusData (PlutusTx.toData datum))
Haskell.error $ Haskell.show $ dr
</code></pre>
<p>which produces the following JSON output:</p>
<pre><code>{
   &quot;constructor&quot;:0,
   &quot;fields&quot;:[
      {
         &quot;bytes&quot;:&quot;74657374&quot;
      },
      {
         &quot;constructor&quot;:0,
         &quot;fields&quot;:[
            {
               &quot;map&quot;:[
                  {
                     &quot;v&quot;:{
                        &quot;bytes&quot;:&quot;74657374&quot;
                     },
                     &quot;k&quot;:{
                        &quot;bytes&quot;:&quot;74657374&quot;
                     }
                  }
               ]
            },
            {
               &quot;map&quot;:[
                  {
                     &quot;v&quot;:{
                        &quot;int&quot;:1
                     },
                     &quot;k&quot;:{
                        &quot;bytes&quot;:&quot;74657374&quot;
                     }
                  }
               ]
            },
            {
               &quot;map&quot;:[
                  {
                     &quot;v&quot;:{
                        &quot;list&quot;:[
                           {
                              &quot;int&quot;:1
                           }
                        ]
                     },
                     &quot;k&quot;:{
                        &quot;bytes&quot;:&quot;74657374&quot;
                     }
                  }
               ]
            }
         ]
      }
   ]
}
</code></pre>
<p>But these are just a separate maps, and Orcfax Datum JSON won't be parsed correctly.
If Map in Orcfax Datum would contain values of identical type, parsing would be easy:</p>
<pre><code>import PlutusTx.AssocMap (Map, fromList)

data OrcfaxDatum = OrcfaxDatum {
    testOne  :: BuiltinByteString,
    testTwo  :: Map BuiltinByteString BuiltinByteString
  } deriving Show
PlutusTx.makeIsDataIndexed ''OrcfaxDatum [('OrcfaxDatum, 0)]
PlutusTx.makeLift ''OrcfaxDatum

-- offchain code
let orcfaxMap = fromList [(&quot;test&quot;, &quot;test&quot;), (&quot;test&quot;, &quot;test&quot;)]
let datum = OrcfaxDatum &quot;test&quot; orcfaxMap
let dr = encode (scriptDataToJson ScriptDataJsonDetailedSchema $ fromPlutusData (PlutusTx.toData datum))
Haskell.error $ Haskell.show $ dr
</code></pre>
<p>Result:</p>
<pre><code>{
   &quot;constructor&quot;:0,
   &quot;fields&quot;:[
      {
         &quot;bytes&quot;:&quot;74657374&quot;
      },
      {
         &quot;map&quot;:[
            {
               &quot;v&quot;:{
                  &quot;bytes&quot;:&quot;74657374&quot;
               },
               &quot;k&quot;:{
                  &quot;bytes&quot;:&quot;74657374&quot;
               }
            },
            {
               &quot;v&quot;:{
                  &quot;bytes&quot;:&quot;74657374&quot;
               },
               &quot;k&quot;:{
                  &quot;bytes&quot;:&quot;74657374&quot;
               }
            }
         ]
      }
   ]
}
</code></pre>
<p>As you can see, the structure is identical.</p>
<p>I think this Datum was built with Mesh or something similar:</p>
<pre><code>import { resolveDataHash } from '@meshsdk/core';
import type { Data } from '@meshsdk/core';

const datumMap: Data = new Map&lt;Data, Data&gt;();
datumMap.set('token', 'meshtoken');
datumMap.set('price', '12345678');
const datumMapHash = resolveDataHash(datumMap);
// datahash: 406f12b8df90412d7af0ff40e80ce62234602ed0b5af2633042b866b1a22b8f4

const datumMap2: Data = new Map&lt;Data, Data&gt;();
datumMap2.set([1, 2], ['meshtoken', 123]);
datumMap2.set([3, 4], 12345678);
const datumMap2Hash = resolveDataHash(datumMap2);
// datahash: 9017cbec493c851cf0f19ff0e69a8188266cefdd9af2210496c55e7a1d743bdb
</code></pre>
<p>What am I missing?</p>
<p>How to parse this Datum onchain with PlutusV2?</p>
<p>How to define type for this map?</p>
<p>thanks</p>

<plutus><datum><json>
Loading specific Datum JSON with Map structure into Plutus type
# Loading specific Datum JSON with Map structure into Plutus type

(Asked by: username_0 on 2023-11-06)

We have a specific Datum, taken from Orcfax oracle UTXO:
https://preprod.cexplorer.io/datum/9ced750ebbb2c9a9eac2e07a91525cadd3bfab23950089faa3e3a55517d1033f
the part we are interested in is the very first field, map:
"map": [
        {
            "k": {
                "bytes": "40636f6e74657874"
            },
            "v": {
                "bytes": "68747470733a2f2f736368656d612e6f7267"
            }
        },
        {
            "k": {
                "bytes": "5f3a636f6e74656e745369676e6174757265"
            },
            "v": {
                "bytes": "61346230303130306537313331386533633130373266343332643930373264376530356230386530666338353333656363323531323861623934653737323937"
            }
        },
        {
            "k": {
                "bytes": "6964656e746966696572"
            },
            "v": {
                "map": [
                    {
                        "k": {
                            "bytes": "70726f70657274794944"
                        },
                        "v": {
                            "bytes": "41726b6c79204964656e746966696572"
                        }
                    },
                    {
                        "k": {
                            "bytes": "74797065"
                        },
                        "v": {
                            "bytes": "50726f706572747956616c7565"
                        }
                    },
                    {
                        "k": {
                            "bytes": "76616c7565"
                        },
                        "v": {
                            "bytes": "75726e3a6f72636661783a61636130373632622d326661372d346461622d396261352d663935333631373430633738"
                        }
                    }
                ]
            }
        },
        {
            "k": {
                "bytes": "6e616d65"
            },
            "v": {
                "bytes": "4144412d5553447c5553442d414441"
            }
        },
        .........................

The strange thing is, values are of a different type. Some are strings, some are lists or integers. As far as I understand, in Plutus/Haskell, AssocMap can contain only values of the same type, and there is no way to declare a type for this Map.
The closest I get to this structure in Plutus is this:
import PlutusTx.AssocMap (Map, fromList)

data OrcfaxDatum = OrcfaxDatum {
    testOne  :: BuiltinByteString,
    testTwo  :: (Map BuiltinByteString BuiltinByteString, Map BuiltinByteString Integer, Map BuiltinByteString [Integer])
  } deriving Show
PlutusTx.makeIsDataIndexed ''OrcfaxDatum [('OrcfaxDatum, 0)]
PlutusTx.makeLift ''OrcfaxDatum

-- in offchain code:
let datum = OrcfaxDatum "test" (fromList [("test", "test")], fromList [("test", 1)], fromList [("test", [1])])
let dr = encode (scriptDataToJson ScriptDataJsonDetailedSchema $ fromPlutusData (PlutusTx.toData datum))
Haskell.error $ Haskell.show $ dr

which produces the following JSON output:
{
   "constructor":0,
   "fields":[
      {
         "bytes":"74657374"
      },
      {
         "constructor":0,
         "fields":[
            {
               "map":[
                  {
                     "v":{
                        "bytes":"74657374"
                     },
                     "k":{
                        "bytes":"74657374"
                     }
                  }
               ]
            },
            {
               "map":[
                  {
                     "v":{
                        "int":1
                     },
                     "k":{
                        "bytes":"74657374"
                     }
                  }
               ]
            },
            {
               "map":[
                  {
                     "v":{
                        "list":[
                           {
                              "int":1
                           }
                        ]
                     },
                     "k":{
                        "bytes":"74657374"
                     }
                  }
               ]
            }
         ]
      }
   ]
}

But these are just a separate maps, and Orcfax Datum JSON won't be parsed correctly.
If Map in Orcfax Datum would contain values of identical type, parsing would be easy:
import PlutusTx.AssocMap (Map, fromList)

data OrcfaxDatum = OrcfaxDatum {
    testOne  :: BuiltinByteString,
    testTwo  :: Map BuiltinByteString BuiltinByteString
  } deriving Show
PlutusTx.makeIsDataIndexed ''OrcfaxDatum [('OrcfaxDatum, 0)]
PlutusTx.makeLift ''OrcfaxDatum

-- offchain code
let orcfaxMap = fromList [("test", "test"), ("test", "test")]
let datum = OrcfaxDatum "test" orcfaxMap
let dr = encode (scriptDataToJson ScriptDataJsonDetailedSchema $ fromPlutusData (PlutusTx.toData datum))
Haskell.error $ Haskell.show $ dr

Result:
{
   "constructor":0,
   "fields":[
      {
         "bytes":"74657374"
      },
      {
         "map":[
            {
               "v":{
                  "bytes":"74657374"
               },
               "k":{
                  "bytes":"74657374"
               }
            },
            {
               "v":{
                  "bytes":"74657374"
               },
               "k":{
                  "bytes":"74657374"
               }
            }
         ]
      }
   ]
}

As you can see, the structure is identical.
I think this Datum was built with Mesh or something similar:
import { resolveDataHash } from '@meshsdk/core';
import type { Data } from '@meshsdk/core';

const datumMap: Data = new Map();
datumMap.set('token', 'meshtoken');
datumMap.set('price', '12345678');
const datumMapHash = resolveDataHash(datumMap);
// datahash: 406f12b8df90412d7af0ff40e80ce62234602ed0b5af2633042b866b1a22b8f4

const datumMap2: Data = new Map();
datumMap2.set([1, 2], ['meshtoken', 123]);
datumMap2.set([3, 4], 12345678);
const datumMap2Hash = resolveDataHash(datumMap2);
// datahash: 9017cbec493c851cf0f19ff0e69a8188266cefdd9af2210496c55e7a1d743bdb

What am I missing?
How to parse this Datum onchain with PlutusV2?
How to define type for this map?
thanks

**Tags:** plutus, datum, json

---

## 1 answers

### Answer by username_1 on 2023-11-08. Score: 2

You could define a union type for values, something like
data Val = B BuiltinByteString
  | M (AssocMap BuiltinByteString Val)

type OrcFax = AssocMap BuiltinByteString Val

then you can deserialise the Datum to a raw Data and "parse" it manually, pattern matching on the parts you are interested in. Data being a generic description of any data structure, allows to mix types this way.


---

