0

I need to create this json object using scala and argonaut:

   "name_value_list":{
      "created_by":{
          "name":"created_by",
          "value":"1"
       },       
       "name":{
          "name":"name",
          "value":"The Name"
       },
       "securitygroup_primary_group":{
           "name":"securitygroup_primary_group",
           "value":""
     }
  }

with scala i'm create this object:

Map("name_value_list" -> (
  Map("created_by"-> Map("name" ->"created_by", "value"->"1")),
  Map("name"-> Map("name" ->"name", "value"->"X")),
  Map("securitygroup_primary_group"-> Map("name" ->"securitygroup_primary_group", "value" ->"")))

But the json generated is this:

   "name_value_list":[{
          "created_by":{
              "name":"created_by",
              "value":"1"
           },       
           "name":{
              "name":"name",
              "value":"The Name"
           },
           "securitygroup_primary_group":{
               "name":"securitygroup_primary_group",
               "value":""
         }
      }]

Can help please?

2 Answers 2

3

The JSON generated contains an Array, but you want a Map instead. In order to find out where you have gone wrong, you should investigate the Scala types you have created before the JSON encoding.

Your code can be refactored to the following:

val tuple = (
  Map("created_by" -> Map("name" -> "created_by", "value" -> "1")),
  Map("name" -> Map("name" -> "name", "value" -> "X")),
  Map("securitygroup_primary_group" -> Map("name" -> "securitygroup_primary_group", "value" -> ""))
)
val toEncode = Map(
  "name_value_list" -> tuple
)

where tuple is of type Tuple3[Map[String, Map[String, String]], Map[String, Map[String, String]], Map[String, Map[String, String]]].

Argonaut naturally converts Tuples into Arrays.

In order to get the JSON you want, you need to change the Tuple into a Map:

val notATuple = Map(
  "created_by" -> Map("name" -> "created_by", "value" -> "1"),
  "name" -> Map("name" -> "name", "value" -> "X"),
  "securitygroup_primary_group" -> Map("name" -> "securitygroup_primary_group", "value" -> "")
)

Where the final answer is:

val toEncode = Map(
  "name_value_list" -> Map(
    "created_by" -> Map("name" -> "created_by", "value" -> "1"),
    "name" -> Map("name" -> "name", "value" -> "X"),
    "securitygroup_primary_group" -> Map("name" -> "securitygroup_primary_group", "value" -> "")
  )
)

A side note: you may find it easier to construct your data with case classes, and then write Codecs to encode them instead. I find case classes easier to reason about than Maps of Maps of Maps.

As of Argonaut 6.1-M5, you can use macros to automatically derive codecs from case classes, like so:

import argonaut._
implicit val codec = CodecJson.derive[YourCaseClass]
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! this works fine, I try to implement Codecs for easy manage data.
-2
Map("name_value_list" -> (
  Map("created_by"-> Map("name" ->"created_by", "value"->"1"),
  "name"-> Map("name" ->"name", "value"->"X"),
  "securitygroup_primary_group"-> Map("name" ->"securitygroup_primary_group", "value" ->""))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.