Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON Representation of Map with Complex Key

I want to serialize to JSON the following (java) data structure:

class Machine {
  String name;
  Map<PartDescriptor, Part> parts;
}

class PartDescriptor {
  String group;
  String id;

  hashCode()
  equals()
}

class Part {
  String group;
  String id;
  String description;
  String compat;
  ...
  ...
}

What would be JSON representation of one Machine?

Also (optional), point me to a JSON to Java serializer/deserializer that will support your representation

like image 575
Op De Cirkel Avatar asked Jun 06 '12 12:06

Op De Cirkel


People also ask

What is [] and {} in JSON?

' { } ' used for Object and ' [] ' is used for Array in json.

Can you use map in JSON?

You can map the data types of your business model into JSON by using the examples. Data in JSON is either an object or an array. A JSON object is an unordered collection of names and values. A JSON array is an ordered sequence of values.


4 Answers

I'd do something like:

{
  "name": "machine name",
  "parts": [
     { "group": "part group", "id": "part id", "description": "...", ... },
     { "group": "part group", "id": "part id", "description": "...", ... },
     // ...
  ]
}

If the "id" for each Part is unique, then the "parts" property can be an object instead of an array, with the "id" of each part serving as the key.

{
  "name": "machine name",
  "parts": {
     "1st part id": { "group": "part group", "description": "...", ... },
     "2nd part id": { "group": "part group", "description": "...", ... },
     // ...
  }
}
like image 177
Pointy Avatar answered Sep 30 '22 07:09

Pointy


You don't need annotations or custom serializers. Assuming you already have getters for all the fields in Part and Machine, all that's really missing is a toString() on PartDescriptor. If, for some reason, you don't have getter functions, you'll need to annotate the fields of interest with @JsonProperty so Jackson knows which fields to include in the serialized output. However, it's preferable (and easier) to simply create getters.

The toString() on PartDescriptor should return the key you want to use in your mapping. As another answer suggests, you might simply concatenate the relevant fields:

@Override
public String toString() {
    return group + "|" + id;
}

Then you'll magically get this form when you attempt to serialize a Machine with Jackson's ObjectMapper:

{
  "name" : "Toaster",
  "parts" : {
    "Electrical|Descriptor1" : {
      "group" : "Electrical",
      "id" : "Part1",
      "description" : "Heating Element",
      "compat" : "B293"
    },
    "Exterior|Descriptor2" : {
      "group" : "Exterior",
      "id" : "Part2",
      "description" : "Lever",
      "compat" : "18A"
    }
  }
}
like image 25
quietmint Avatar answered Sep 30 '22 07:09

quietmint


I would do this. The parts key of the top level object would be a JSONArray of JSONObject that have key's and value's. The key would be an object that is your PartDescriptor and the value would be your Part.

{
    "name":"theName",
    "parts":[
        {
            "key":{
                       "group":"theGroup",
                       "id":"theId"
                  },
            "value":{
                       "group":"theGroup",
                       "id":"theId",
                       "description":"theDescription",
                       "compat":"theCompat",
                       ...
                    }
        },
        ...
    ]
}
like image 21
nicholas.hauschild Avatar answered Sep 30 '22 05:09

nicholas.hauschild


Assuming that group+id gives a unique combination, and that ":" is a permissible delimiter:

{  
   "name": "machine name",
   "parts": { 
               "somegroup:01465": {
                                    "group":"somegroup",
                                    "id": "01465",
                                    ...
                                  },
               "othergroup:32409": {
                                     "group":"othergroup",
                                     "id": "32409",
                                     ...
                                   }

            }
}
like image 29
Phil H Avatar answered Sep 30 '22 06:09

Phil H