Преобразовать строки yaml в объекты JSON - PullRequest
1 голос
/ 19 сентября 2019

У нас есть две отдельные кодовые базы, которые используют разные стили локализации.Одна из кодовых баз использует yaml, другая использует JSON.

В настоящее время мы медленно мигрируем в кодовую базу с JSON, но с 20-тысячными строками yaml и 7 различными языками это трудная задача для преобразованияэто все вручную.К сожалению, мы используем строковую нотацию, а не нотацию объектов в наших файлах yaml, поэтому конвертер типа this не будет работать.

Пример yaml

cart.title.primary: Cart
cart.title.secondary: Buy products
cart.dialog.title: Remove product
cart.dialog.text: Are you sure to remove this product?

становится вэто конвертер

{
  "cart.title.primary": "Cart",
  "cart.title.secondary": "Buy products",
  "cart.dialog.title": "Remove product",
  "cart.dialog.text": "Are you sure to remove this product?"
}

Но я хочу, чтобы каждая точка в строке на самом деле была объектом в JSON.Поэтому в идеале ямл должен был выглядеть примерно так:

{
  "cart": {
    "title": {
      "primary": "Cart",
      "secondary: "Buy Products"
    },
    "dialog": {
      "title": "Remove product",
      "text": "Are you sure to remove this product?"
    }
  }
}

Есть ли кто-то с опытом, делающий что-то подобное?Прив.используя PHP или JavaScript.Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 19 сентября 2019

Как сценарий Node.js.

#!/usr/bin/env node

const fs = require('fs')

var file = process.argv[process.argv.length - 1]
var json = {}
fs.readFileSync(file, { encoding: 'utf8' })
  .split(/\r?\n/)
  .forEach((line) => {
    [keyPath, value] = line.split(/: */)
    var target = json
    var keys = keyPath.split(/\./)
    var counter = 0
    keys.forEach((key) => {
      counter++
      if (counter === keys.length) target[key] = value
      else {
        if (!(key in target)) target[key] = {}
        target = target[key]
      }
    })
  })
console.log(JSON.stringify(json, null, 2))

Чтобы использовать его:

convert.js file.yaml

Вывод, используя ваш example.yaml в качестве ввода:

{
  "cart": {
    "title": {
      "primary": "Cart",
      "secondary": "Buy products"
    },
    "dialog": {
      "title": "Remove product",
      "text": "Are you sure to remove this product?"
    }
  }
}
1 голос
/ 19 сентября 2019

Вы можете использовать комбинацию базовой загрузки yaml, это просто предполагает строку и использует yaml_parse(), а затем использует код из Синтаксис преобразования точки как, например, this.that.other"к многомерному массиву в PHP вы можете обрабатывать каждую строку за раз, чтобы создать новую структуру ...

$yaml = 'cart.title.primary: Cart
cart.title.secondary: Buy products
cart.dialog.title: Remove product
cart.dialog.text: Are you sure to remove this product?';

$data = yaml_parse($yaml);

$output = [];
foreach ( $data as $key => $entry ) {
    assignArrayByPath($output, $key, $entry);
}

function assignArrayByPath(&$arr, $path, $value, $separator='.') {
    $keys = explode($separator, $path);

    foreach ($keys as $key) {
        $arr = &$arr[$key];
    }

    $arr = $value;
}

echo json_encode($output, JSON_PRETTY_PRINT);

, которая дает вам

{
    "cart": {
        "title": {
            "primary": "Cart",
            "secondary": "Buy products"
        },
        "dialog": {
            "title": "Remove product",
            "text": "Are you sure to remove this product?"
        }
    }
}
0 голосов
/ 19 сентября 2019

Вы можете построить эту вложенную структуру, используя метод split для создания массива путей из ключей, а затем метод reduce для вложения свойств на основе этого массива ключей.

const yaml = {
  "cart.title.primary": "Cart",
  "cart.title.secondary": "Buy products",
  "cart.dialog.title": "Remove product",
  "cart.dialog.text": "Are you sure to remove this product?"
}

const toJson = (data) => {
  return Object.keys(data).reduce((a, k) => {
    k.split('.').reduce((r, e, i, a) => {
      return r[e] || (r[e] = (a[i + 1] ? {} : data[k]))
    }, a)
    return a
  }, {})
}

console.log(toJson(yaml))

Вы также можете использовать метод split, чтобы разбить строку yaml на новые строки, а затем построить вложенный объект с помощью reduce.

const yaml = `
cart.title.primary: Cart
cart.title.secondary: Buy products
cart.dialog.title: Remove product
cart.dialog.text: Are you sure to remove this product?
`
const obj = yaml.split('\n').filter(Boolean).reduce((a, k) => {
  const [key, value] = k.split(': ')

  key.split('.').reduce((r, e, i, arr) => {
    return r[e] || (r[e] = (arr[i + 1] ? {} : value))
  }, a)

  return a;
}, {})

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