shell 替换深嵌入JSON文件中的特定键

368yc8dk  于 2023-01-09  发布在  Shell
关注(0)|答案(1)|浏览(90)

我有一个本地生成的json文件(origin.json),我想替换这个origin.json中的一些键并生成一个remote.json,这样我就可以按照它的端点有效负载格式将它发送到远程服务器。
我的origin.json很大,而且嵌入很深,我可以迭代每个键并替换我需要的键,但是我想知道是否有一个高效的工具可以做同样的事情?比如jq?
下面是我的嵌入式json

{
        "timeoutMs": 3000,
        "requestTopic": "local-cron",
        "searchQuery": {
            "checkin": "2023-01-10",
            "checkout": "2023-01-11",
            "numberRoomsNeeded": 0,
            "adultsTotal": 2,
            "childrenTotal": 0,
            "currency": "EUR"
        },
        "requestContext": {
            "userId": 666666666,
            "userAuthLevel": 2,
            "isUserstar": true,
            "visitorCc1": "cn",
            "trafficSourceId": 0,
            "siteTypeId": 9,
            "detectedUserType": "normal",
            "travelPurpose": 2,
            "affiliateId": 12345,
            "languageCode": "en-us",
            "currency": "CNY",
            "siteType": 1,
            "serverRole": "cron",
            "action": "bp",
            "visitorIdentifier": [
                {
                    "type": "id-single",
                    "uvi": "00000000000000000000000"
                },
                {
                    "type": "user-identity",
                    "uvi": "66666666"
                },
                {
                    "type": "user",
                    "uvi": "77777777777"
                }
            ],
            "isInternal": true,
            "enableExperiments": true,
            "shouldTrackRequestInExperiments": true,
            "starSettings": {
                "isUserstar": true,
                "isUserstarControlGroup": false,
                "canStarUserSeeFreeBreakfast": true,
                "canStarUserSeeFreeRoomUpgrade": true,
                "starTier": 5,
                "topstarBenefit": "",
                "isRightstar": true,
                "starDynamicPricing": {
                    "canSeestarDynamicPricingLevel3": true
                },
                "canStarUserSeeFreeCleaningFee": true,
                "starVipSettings": [
                    {
                        "eligible": true,
                        "benefitName": "no_et",
                        "programType": "PriceMatchTrial",
                        "percentage": 0
                    }
                ]
            },
            "isCsRelocationMode": false,
            "tripValueContext": {},
            "visitorCountryRegion": "sh",
            "paymentTiming": 1,
            "includeConditional": false
        },
        "showDebug": false,
        "hits": [
            {
                "hhhhid": 8228082,
                "ppblock": {
                    "allMatchingBlocks": [
                        {
                            "blockId": 1,
                            "rawBlock": {
                                "occupancy": 2,
                                "price": 34425,
                                "roomId": 822808201,
                                "policygroupId": 346547507,
                                "mealplan": 2,
                                "channel": 581,
                                "currencyId": 2,
                                "maxPersons": 3,
                                "flags": 0,
                                "freeCancelUntil": 0,
                                "priceBase10Exponent": -2,
                                "packageId": 0,
                                "paymenttermsId": 38,
                                "vrFlags": 0,
                                "bundleId": 0
                            },
                            "blockStay": {
                                "stayNights": [
                                    {
                                        "polId": 346547507,
                                        "rateId": 25728208,
                                        "curId": 2,
                                        "price": 344.25,
                                        "price1": 0,
                                        "channelId": 581,
                                        "occupancy": 2,
                                        "roomId": 822808201,
                                        "initialPrice": 405,
                                        "initialPrice1": 0
                                    }
                                ],
                                "stayNrRooms": 1,
                                "stayAvailableUntil": 1956105,
                                "stayPrice": 344.25,
                                "stayFlashDeal": 0,
                                "stayPromoTextId": 0,
                                "stayMinAdvanceRes": 1673388000,
                                "stayInventorySegmentId": 0,
                                "stayExperimentFlags": 0,
                                "stayRoomRateFlags": 4,
                                "stayIncludedProducts": 0
                            }
                        }
                        ]
                    },
                    "selectedBlocks": [
                        "822808201_346547507_2_2_0"
                    ],
                    "selected": {
                        "822808201_346547507_2_2_0": 1
                    }
                }
            ],
            "pipeline": 3
}

我在这里标记了几个要替换为**'==〉(new key)'**的键

jq '.. | keys?' star-dragongate.json 
[
  "hits",
  "pipeline",
  "requestContext",
  "requestTopic",
  "searchQuery",
  "showDebug", ==> showdebug 
  "timeoutMs"
]
[
  "adultsTotal",
  "checkin",
  "checkout",
  "childrenTotal",
  "currency",
  "numberRoomsNeeded"
]
[
  "action",
  "affiliateId", ==> Affilateid
  "currency",
  "detectedUserType",
  "enableExperiments",
  "starSettings",
  "includeConditional",
  "isCsRelocationMode",
  "isInternal",
  "isUserstar",
  "languageCode",
  "paymentTiming",
  "serverRole",
  "shouldTrackRequestInExperiments", ==> inexperiments
  "siteType",
  "siteTypeId",
  "trafficSourceId",
  "travelPurpose",
  "tripValueContext",
  "userAuthLevel",
  "userId",
  "visitorCc1",
  "visitorCountryRegion",
  "visitorIdentifier"
]
[
  0,
  1,
  2
]
[
  "type",
  "uvi"
]
[
  "type",
  "uvi"
]
[
  "type",
  "uvi"
]
[
  "canStarUserSeeFreeBreakfast",
  "canStarUserSeeFreeCleaningFee",
  "canStarUserSeeFreeRoomUpgrade",  ==> freeroom_upgrade
  "starDynamicPricing",
  "starTier",
  "starVipSettings",
  "isRightstar",
  "isUserstar",
  "isUserstarControlGroup",
  "topstarBenefit"
]
[
  "canSeestarDynamicPricingLevel3"
]
[
  0
]
[
  "benefitName",
  "eligible",
  "percentage",
  "programType"
]
[]
[
  0
]
[
  "hhhhid",
  "ppblock",
  "selected",
  "selectedBlocks"
]
[
  "allMatchingBlocks"
]
[
  0
]
[
  "blockId",
  "blockStay",
  "rawBlock"
]
[
  "bundleId",  ==> bundle_id
  "channel",
  "currencyId",
  "flags",
  "freeCancelUntil",
  "maxPersons",
  "mealplan",
  "occupancy",
  "packageId",
  "paymenttermsId",
  "policygroupId",
  "price",
  "priceBase10Exponent",
  "roomId",
  "vrFlags"
]
[
  "stayAvailableUntil",
  "stayExperimentFlags",
  "stayFlashDeal",
  "stayIncludedProducts",
  "stayInventorySegmentId",
  "stayMinAdvanceRes",
  "stayNights",
  "stayNrRooms",
  "stayPrice",
  "stayPromoTextId", ==> staypromotextid
  "stayRoomRateFlags"
]
[
  0
]
[
  "channelId",
  "curId",
  "initialPrice",
  "initialPrice1",
  "occupancy",
  "polId",
  "price",
  "price1",
  "rateId",
  "roomId"
]
[
  0
]
[
  "822808201_346547507_2_2_0"
]

我需要替换的键位于这个json的不同嵌入层和块中。有没有关于如何有效地替换这些键的建议?PS:json文件中的键位于静态位置,不会一直动态变化。

pvcm50d1

pvcm50d11#

要重命名一个字段名,可以使用with_entries,它允许您访问每个.key。通过赋值重置它。
现在,还不清楚的是您希望如何找到所讨论的键(通过编程方式),如果它们的位置是静态的,并且您知道它们,则单独处理它们,如下所示:

.requestContext.starSettings |= with_entries((.key | select(. == "canStarUserSeeFreeRoomUpgrade")) = "freeroom_upgrade")
| .hits[].ppblock.allMatchingBlocks[].rawBlock |= with_entries((.key | select(. == "bundleId")) = "bundle_id")
# and so on...

为了减少冗余代码,您也可以将重命名部分移到它自己的函数中,然后调用它,例如:

def rename($old; $new):
  with_entries((.key | select(. == $old)) = $new);

.requestContext.starSettings |= rename("canStarUserSeeFreeRoomUpgrade"; "freeroom_upgrade")
| .hits[].ppblock.allMatchingBlocks[].rawBlock |= rename("bundleId";  "bundle_id")
# and so on...

或者将位置也移动到函数中,例如:

def rename_at(path; $old; $new):
  path |= with_entries((.key | select(. == $old)) = $new);

rename_at(.requestContext.starSettings; "canStarUserSeeFreeRoomUpgrade"; "freeroom_upgrade")
| rename_at(.hits[].ppblock.allMatchingBlocks[].rawBlock; "bundleId";  "bundle_id")
# and so on...

如果它们的位置未知,而你想只根据它们的(本地)名称替换它们,你需要遍历文档,检查是否找到匹配的名称。walk函数提供了遍历功能,objects将操作减少到对象:

walk(objects |= with_entries(
  if .key == "canStarUserSeeFreeRoomUpgrade" then .key = "freeroom_upgrade"
  elif .key == "bundleId" then .key = "bundle_id"
  # and so on...
  else . end
))

相关问题