поля фильтра groovy в ответе json

#javascript #json #groovy

#javascript #json #groovy

Вопрос:

Я пытаюсь отфильтровать некоторые поля в моем ответе JSON. Пример ответа ниже:

 {
  "Status": "Fail",
  "Code": "500",
  "Rules": [{
      "Status": "Fail",
      "Message": "Code error",
      "id": "123456"
    },
    {
      "Status": "Fail",
      "Message": "Configuration error",
      "id": "12345"
    }
  ]
}
 

Я хочу опустить поля кода и идентификатора и распечатать остальные поля в JSON.
окончательный ответ должен выглядеть следующим образом:-

 {
  "Status": "Fail",
  "Rules": [{
      "Status": "Fail",
      "Message": "Code error"
    },
    {
      "Status": "Fail",
      "Message": "Configuration error"
    }
  ]
}
 

Есть идеи о том, как мы можем этого добиться?

Ответ №1:

Groovy уже предоставляет классы и механизмы для этого, сначала вам нужно импортировать класс groovy.json.JsonGenerator

Затем вы можете определить поля, которые вы хотите игнорировать при серилизации:

 def generator = new JsonGenerator.Options()
    .excludeFieldsByName('id', 'Code')
    .build()
 

И, наконец, просто нужно проанализировать вывод:

 String output = generator.toJson(input)
 

Результат будет выглядеть примерно так:

 {
    "Status": "Fail",
    "Rules": [
        {
            "Status": "Fail",
            "Message": "Code error"
        },
        {
            "Status": "Fail",
            "Message": "Configuration error"
        }
    ]
}
 

Вот полный пример того, как я это сделал:

 import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import groovy.json.JsonGenerator

String json = '''{
  "Status": "Fail",
  "Code": "500",
  "Rules": [{
      "Status": "Fail",
      "Message": "Code error",
      "id": "123456"
    },
    {
      "Status": "Fail",
      "Message": "Configuration error",
      "id": "12345"
    }
  ]
}'''

Map input = new JsonSlurper().parseText(json)

def generator = new JsonGenerator.Options()
    .excludeFieldsByName('id', 'Code')
    .build()

String output = generator.toJson(input)

println JsonOutput.prettyPrint(output)
 

Чтобы увидеть больше конфигураций для этого класса JsonGenerator, вы можете перейти к официальной документации здесь: https://groovy-lang.org/json.html#_customizing_output

Комментарии:

1. Получение приведенной ниже ошибки при использовании генератора. сбой запуска: GroovyUserScript : 3: не удалось разрешить класс groovy.json. JsonGenerator @ строка 3, столбец 1. импортируйте groovy.json. JsonGenerator ^ GroovyUserScript : 23: не удалось разрешить класс JsonGenerator. Параметры @ строка 23, столбец 17. def generator = новый JsonGenerator. Параметры ()

2. Я забыл упомянуть, что я использую groovy 3.0.6 для этого примера, возможно, если вы попробуете с этой версией, вы больше не увидите эту ошибку.

3. Спасибо за это, я все время забываю класс JasonGenerator и возвращаюсь к старым привычкам. Я думаю, что это должно быть общепринятым ответом до тех пор, пока мы используем более позднюю версию groovy и до тех пор, пока op нужно фильтровать только выходную строку, а не структуру groovy map / list.

Ответ №2:

 var getData = {
  "Status": "Fail",
  "Code": "500",
  "Rules": [{
      "Status": "Fail",
      "Message": "Code error",
      "id": "123456"
    },
    {
      "Status": "Fail",
      "Message": "Configuration error",
      "id": "12345"
    }
  ]
};
delete getData.Code;
for (var i = 0; i < getData.Rules.length; i  ) {
  delete getData.Rules[i].id;
}
console.log(getData); 

Примечание: — Вы можете просто использовать delete elementValue для достижения этого

Комментарии:

1. Спасибо, это будет сложнее, когда у нас будут подробные рекурсивные данные, которые есть в моем случае. Есть ли способ, которым мы выбираем определенные поля и создаем новый json вместо удаления полей.

Ответ №3:

 const obj = {
    "Status": "Fail",
    "Code": "500",
    "Rules": [
        {
            "Status": "Fail",
            "Message": "Code error",
            "id": "123456"
        },
        {
            "Status": "Fail",
            "Message": "Configuration error",
            "id": "12345"
        }
    ]
}

const result = Object.keys(obj).reduce((acc, curr) => {
  if (curr !== "Code") {
    acc = {
      ...acc,
      [curr]: obj[curr]
    }
  }
  if (curr === "Rules") {
    acc = {
      ...acc,
      [curr]: obj[curr].map(rule => {
        delete rule.id
        return rule
      })
    }
  }
  return acc
}, {})

console.log(result) 

Ответ №4:

Решение, которое рекурсивно просматривает ваш json и удаляет определенные поля на любой глубине:

 import groovy.json.*

def str = '''
{
  "Status": "Fail",
  "Code": "500",
  "Rules": [{
      "Status": "Fail",
      "Message": "Code error",
      "id": "123456"
    },
    {
      "Status": "Fail",
      "Message": "Configuration error",
      "id": "12345"
    }
  ]
}'''

def json  = new JsonSlurper().parseText(str)
def clean = recursivelyRemove(json, ['id', 'Code'])

println JsonOutput.prettyPrint(JsonOutput.toJson(clean))

def recursivelyRemove(obj, fieldNames) {
  switch(obj) {
    case Map:
      obj.findAll { k, v -> 
        !(k in fieldNames)
      }.collectEntries { k, v -> 
        [k, recursivelyRemove(v, fieldNames)]
      }
      break
    case List:
      obj.collect { recursivelyRemove(it, fieldNames) }
      break
    default: 
      obj
  }
}
 

который печатает:

 
─➤ groovy solution.groovy                                                                                              1 ↵
{
    "Status": "Fail",
    "Rules": [
        {
            "Status": "Fail",
            "Message": "Code error"
        },
        {
            "Status": "Fail",
            "Message": "Configuration error"
        }
    ]
}
 

при запуске.

Это имеет тот плюс, что он не жестко запрограммирован для вашей структуры json, т. Е. Если структура по какой-то причине изменится, этот код все равно может работать.

Потенциальным недостатком является то, что если ваша структура json очень глубокая (скажем, сотни или тысячи уровней вложенности), вы можете получить исключение StackOverflowException при выполнении рекурсивных вызовов. Это может быть или не быть вероятным в зависимости от вашего сценария.

Комментарии:

1. Правильно, мои данные очень рекурсивны. более того, это работает, когда мы объявляем статические данные в переменной. я попробовал это на данных, которые являются ответом на вызов API, который не сработал.

2. Я бы предположил, что в данных ответа есть какая-то структурная разница. Есть ли шанс, что вы могли бы добавить этот образец данных к вопросу?

3. JsonSlurper.parseText печатается как {Status=Fail, Code= 500, Rules=[{}, {id = 12345}]}, когда я тестирую в IDE, но то же самое, когда я печатаю на этапе Jenkins, он печатает [Status:Fail, Code:500, Rules:[[], {id:12345]]]. Есть идеи, почему фигурные скобки и = печатаются по-другому?

4. Можно предположить, что ответ json отличается между двумя вызовами, но трудно сказать без дополнительной информации. Если синтаксический анализ завершится неудачно, это, вероятно, будет означать, что данные in не являются допустимыми json. Это более распространенное явление, чем вы думаете. Пропущенные кавычки, пропущенные запятые, искаженные имена идентификаторов и т.д.