Как получить подстроку с использованием шаблонов и заменить кавычки в поле значения JSON с помощью Scala? - PullRequest
0 голосов
/ 20 мая 2018

У меня есть несколько сообщений json, таких как

{"column1":"abc","column2":"123","column3":qwe"r"ty,"column4":"abc123"}
{"column1":"defhj","column2":"45","column3":asd"f"gh,"column4":"def12d"}

Мне нужно добавить двойные кавычки в обе стороны для значения column3 и заменить двойные кавычки в значении column3 одинарными кавычками, используя scala.

Ответы [ 2 ]

0 голосов
/ 21 мая 2018

Цель

добавить двойные кавычки в обе стороны для значения column3 и заменить двойные кавычки в значении column3 одинарными кавычками, используя scala.

Я бы рекомендовал использовать RegEx, потому что у вас больше гибкости.

Вот решение:

val kafkaMsg = List("""{"column1":"abc","column2":"123","column3":qwe"r"ty,"column4":"abc123"}""", """{"column1":"defhj","column2":"45","column3":asd"f"gh,"column4":"def12d"}""", """{"column1":"defhj","column2":"45","column3":without-quotes,"column4":"def12d"}""")
val rdd = sc.parallelize(kafkaMsg)
val rePattern = """(^\{.*)("column3":)(.*)(,"column4":.*)""".r
val newRdd = rdd.map(r => 
    r match { 
        case rePattern(start, col3, col3Value, end) => (start + col3 + '"' + col3Value.replaceAll("\"", "'") + '"' + end)
        case _ => r }
    )

newRdd.foreach(println)

Объяснение:

  1. Первый и второй операторы являются инициализацией rdd.

  2. Третья строка определяет шаблон регулярного выражения.Возможно, вам придется настроить его в соответствии с вашей ситуацией.

    Regex выдает 4 группы значений (все, что в () является группой):

    • строка, начинающаяся с "{" ипосле того, как мы встретим "column3":
    • "column3": само по себе
    • все, что будет после "column3": но до "column4":
    • что бы ни начиналось,"column4":

    Я использую эти 4 группы в следующем выражении.

  3. Перебираем свой rdd, запускаем его для регулярного выражения и меняем его: заменяем doubleкавычки с одиночными, и добавить открытые / закрытые кавычкиВ случае отсутствия совпадения будет возвращена исходная строка.

    Поскольку регулярное выражение было определено для 4 групп, я использую 4 переменные для сопоставления совпадений:

    case rePattern(start, col3, col3Value, end) =>
    

    Примечание: код не соответствуетпроверьте, есть ли у вас двойная кавычка в значении или нет, он просто запускает обновление.Вы можете добавить проверку самостоятельно, если вам нужно.

  4. Показать результаты.

Важные примечания: RegexЯ использовал строго связан с вашим исходным форматом строки.Имейте в виду, что у вас есть JSON, поэтому порядок ваших ключей не гарантируется.В результате вы можете получить «column4» (которое используется как окончание значения column3) перед «column3».

Если вы используете запятую в качестве окончания ключа / значения, убедитесь, что вы неон должен быть частью значения column3.

Итог: вам нужно настроить мое регулярное выражение, чтобы правильно определить значение конца column3.

Надеюсь, это поможет.

0 голосов
/ 20 мая 2018

Вы упомянули в комментарии выше

У меня огромный набор данных в kafka. Я пытаюсь читать из kafka и писать в hdfs через spark, используя scala.Я использую json parserно не удалось разобрать из-за проблемы column3. так что нужно манипулировать сообщением, чтобы оно превратилось в json

Таким образом, у вас должен быть сбор искаженных jsons, как в вопросе.Я создал список как

val kafkaMsg = List("""{"column1":"abc","column2":"123","column3":qwe"r"ty,"column4":"abc123"}""", """{"column1":"defhj","column2":"45","column3":asd"f"gh,"column4":"def12d"}""")

, и вы читаете его через Spark, так что вы должны иметь rdds как

val rdd = sc.parallelize(kafkaMsg)

Все, что вам нужно, это какой-то синтаксический анализ искаженного текста json длясделайте его действительной строкой json как

val validJson = rdd.map(msg => msg.replaceAll("[}\"{]", "").split(",").map(_.split(":").mkString("\"", "\":\"", "\"")).mkString("{", ",", "}"))

validJson должно быть

{"column1":"abc","column2":"123","column3":"qwerty","column4":"abc123"}
{"column1":"defhj","column2":"45","column3":"asdfgh","column4":"def12d"}

Вы можете создать фрейм данных из validJson rdd как

sqlContext.read.json(validJson).show(false)

, что должно дать вам

+-------+-------+-------+-------+
|column1|column2|column3|column4|
+-------+-------+-------+-------+
|abc    |123    |qwerty |abc123 |
|defhj  |45     |asdfgh |def12d |
+-------+-------+-------+-------+

Или вы можете сделать согласно вашему требованию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...