简体   繁体   中英

JOLT shift transformation: filter by inner value of a property (not the name) - only some properties

I am trying to transform a JSON using Jolt transformation looking for some input here. I am trying to filter by the inner value of the attribute.

My goal is to get an array that contains only the items with the typeName 'xx'. But not all the item object, only some of the fields

{
  "id": "11_1",
  "action": "add",
  "payment": {
    "paied": true,
    "coin": "dollar"
  },
  "type": {
    "id": "11_1_xx",
    "typeName": "xx"
  },
  "details": {
    "place": {
      "id": "123",
      "name": "xx"
    },
    "status": {
      "id": "123",
      "name": "xx"
    }
  }
}

Here is my input and expected output:

Input :

{
  "id": 11,
  "item": [
    {
      "id": "11_1",
      "action": "add",
      "payment": {
        "paied": true,
        "coin": "dollar"
      },
      "type": {
        "id": "11_1_xx",
        "typeName": "xx",
        "typeGroup": "xx",
        "typeValue": "xx"
      },
      "details": {
        "place": {
          "id": "123",
          "name": "xx"
        },
        "status": {
          "id": "123",
          "name": "xx"
        },
        "reason": {
          "id": "123",
          "name": "xx"
        }
      },
      "item": [
        {
          "id": "11_1_1",
          "action": "add",
          "payment": {
            "paied": true,
            "coin": "dollar"
          },
          "type": {
            "id": "11_1_1_zz",
            "typeName": "zz",
            "typeGroup": "zz",
            "typeValue": "zz"
          },
          "details": {
            "place": {
              "id": "123",
              "name": "xx"
            },
            "status": {
              "id": "123",
              "name": "xx"
            },
            "reason": {
              "id": "123",
              "name": "xx"
            }
          },
          "item": [
            {
              "id": "11_1_1_1",
              "action": "add",
              "payment": {
                "paied": true,
                "coin": "NIS"
              },
              "type": {
                "id": "11_1_1_1_xx",
                "typeName": "xx",
                "typeGroup": "xx",
                "typeValue": "xx"
              },
              "details": {
                "place": {
                  "id": "123",
                  "name": "xx"
                },
                "status": {
                  "id": "123",
                  "name": "xx"
                },
                "reason": {
                  "id": "123",
                  "name": "xx"
                }
              }
            }
          ]
        },
        {
          "id": "11_1_2",
          "action": "add",
          "payment": {
            "paied": false,
            "coin": "dollar"
          },
          "type": {
            "id": "11_1_2_xx",
            "typeName": "xx",
            "typeGroup": "xx",
            "typeValue": "xx"
          },
          "details": {
            "place": {
              "id": "123",
              "name": "xx"
            },
            "status": {
              "id": "123",
              "name": "xx"
            },
            "reason": {
              "id": "123",
              "name": "xx"
            }
          },
          "item": [
            {
              "id": "11_1_2_1",
              "action": "add",
              "payment": {
                "paied": false,
                "coin": "NIS"
              },
              "type": {
                "id": "11_1_2_1_zz",
                "typeName": "zz",
                "typeGroup": "zz",
                "typeValue": "zz"
              },
              "details": {
                "place": {
                  "id": "123",
                  "name": "xx"
                },
                "status": {
                  "id": "123",
                  "name": "xx"
                },
                "reason": {
                  "id": "123",
                  "name": "xx"
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

Expected output :

[
  {
    "id": "11_1",
    "action": "add",
    "payment": {
      "paied": true,
      "coin": "dollar"
    },
    "type": {
      "id": "11_1_xx",
      "typeName": "xx"
    },
    "details": {
      "place": {
        "id": "123",
        "name": "xx"
      },
      "status": {
        "id": "123",
        "name": "xx"
      }
    }
  },
  {
    "id": "11_1_1_1",
    "action": "add",
    "payment": {
      "paied": true,
      "coin": "NIS"
    },
    "type": {
      "id": "11_1_1_1_xx",
      "typeName": "xx"
    },
    "details": {
      "place": {
        "id": "123",
        "name": "xx"
      },
      "status": {
        "id": "123",
        "name": "xx"
      }
    }
  },
  {
    "id": "11_1_2",
    "action": "add",
    "payment": {
      "paied": false,
      "coin": "dollar"
    },
    "type": {
      "id": "11_1_2_xx",
      "typeName": "xx"
    },
    "details": {
      "place": {
        "id": "123",
        "name": "xx"
      },
      "status": {
        "id": "123",
        "name": "xx"
      }
    }
  }
]

Can you please help me to write a simple spec that will do this?

You can use the following explained spec

[
  {
    // Determine all key-value pairs partitioned under the main value and type.typeValue combinations 
    "operation": "shift",
    "spec": {
      "item": {
        "*": {
          "item": {
            "*": {
              "item": {
                "*": {
                  "type": {
                    "@(1,id)": "@(2,id).@(1,typeName).id", //traverse } character twice in order to reach the main id of the object
                    "@(1,action)": "@(2,id).@(1,typeName).action",
                    "*": "@(2,id).@(1,typeName).&1.&" // &1 replicates "type" key, & does the leaf value
                  },
                  "*": "@(1,id).@(1,type.typeName).&"
                }
              },
              "type": {
                "@(1,id)": "@(2,id).@(1,typeName).id",
                "@(1,action)": "@(2,id).@(1,typeName).action",
                "*": "@(2,id).@(1,typeName).&1.&"
              },
              "*": "@(1,id).@(1,type.typeName).&"
            }
          },
          "type": {
            "@(1,id)": "@(2,id).@(1,typeName).id",
            "@(1,action)": "@(2,id).@(1,typeName).action",
            "*": "@(2,id).@(1,typeName).&1.&"
          },
          "*": "@(1,id).@(1,type.typeName).&"
        }
      }
    }
  },
  {
    // Filter out by the desired value(in this case it's "xx") 
    "operation": "shift",
    "spec": {
      "*": {
        "xx": ""
      }
    }
  },
  {
    // Get rid of same repeating components of id and action arrays
    "operation": "cardinality",
    "spec": {
      "*": {
        "id": "ONE",
        "action": "ONE"
      }
    }
  },
  {
    // Get rid of undesired attributes
    "operation": "remove",
    "spec": {
      "*": {
        "type": {
          "typeGroup": "",
          "typeValue": ""
        },
        "det*": {
          "reason": ""
        }
      }
    }
  }
]

You may try library Josson . Function map() build a new ObjectNode. Function field() modify the current ObjectNode and can be used to remove fields. The transformation statement is short and easy to understand.

https://github.com/octomix/josson

Josson josson = Josson.fromJsonString(inputJSON);
JsonNode node = josson.getNode(
    "cumulateCollect(" +
    "    [type.typeName='xx']" +              // filter
    "        .field(type.map(id, typeName)" + // need "type.id" and "type.typeName"
    "              ,details.field(reason:)" + // remove "details.reason"
    "              ,item:)" +                 // remove "item"
    "   ,item)");                             // next round
System.out.println(node.toPrettyString());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM