Как можно безопасным образом преобразовать атрибут html (объект Javascript) в массив в Javascript/Jquery?

У меня есть следующий элемент HTML, содержащий объект javascript:

<div ui-jq = "easyPieChart"
     ui-options = "{
                 percent: 75,
                 lineWidth: 5,
                 trackColor: '#e8eff0',
                 barColor: '#23b7e5',
                 scaleColor: false,
                 color: '#3a3f51',
                 size: 134,
                 lineCap: 'butt',
                 rotate: -90,
                 animate: 1000
                 }"
     class = "easyPieChart">
</div>

Как я могу преобразовать эту строку в массив, как показано ниже, без изменения HTML:

[{
  animate: 1000,
  barColor: "#23b7e5",
  color: "#3a3f51",
  lineCap: "butt",
  lineWidth: 5,
  percent: 75,
  rotate: -90,
  scaleColor: false,
  size: 134,
  trackColor: "#e8eff0"
}]

Я уже пробовал эти версии:

$("[ui-jq]").each(function () {
  var self = $(this);
  // var options = eval('[' + self.attr('ui-options') + ']');
  var options = (new Function("return [" + self.attr('ui-options') + "];")());

  console.info(options);
});

Но я получаю сообщение об ошибке относительно CSP:

Content Security Policy of your site blocks the use of 'eval' in JavaScript

The Content Security Policy (CSP) prevents the evaluation of arbitrary strings as JavaScript to make it more difficult for an attacker to inject unauthorized code on your site.

To solve this issue, avoid using eval(), new Function(), setTimeout([string], ...) and setInterval([string], ...) for evaluating strings.

Я создал этот JSFiddle, чтобы помочь вам быстрее показать мне пример: https://jsfiddle.net/oqwc1j58/4/

Спасибо

Ну, не меняйте HTML, если не хотите, но вы просто усложняете себе жизнь/

Pointy 27.12.2022 17:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если вы сделаете атрибут атрибутом data- и сделаете значение правильным JSON, то jQuery сделает это за вас:

    $("[ui-jq]").each(function () {
      var self = $(this);
      var options = self.data("uiOptions");
    
      console.info(options);
    });
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div ui-jq = "easyPieChart"
     data-ui-options='{
                 "percent": 75,
                 "lineWidth": 5,
                 "trackColor": "#e8eff0",
                 "barColor": "#23b7e5",
                 "scaleColor": false,
                 "color": "#3a3f51",
                 "size": 134,
                 "lineCap": "butt",
                 "rotate": -90,
                 "animate": 1000
                 }'
       class = "easyPieChart">
    </div>

Когда jQuery видит, что значение атрибута data- может быть проанализировано как действительный JSON, он делает это неявно и возвращает результирующее значение, когда вы загружаете его через .data(). Обратите внимание, что следует использовать версию имени в верблюжьем регистре (я думаю), но jQuery может работать с любой версией. Обратите также внимание, что вы опускаете префикс «data-».

Спасибо за ваш ответ, но я не могу изменить HTML.

Lucian-Ionut Turiac 27.12.2022 17:52

Это немного странно, но вы можете самостоятельно проанализировать HTML и создать массив, который вы ищете:

// From https://stackoverflow.com/a/72773057/378779
const sortObjectByKeys = (object, asc = true) => Object.fromEntries(
  Object.entries(object).sort(([k1], [k2]) => k1 < k2 ^ !asc ? -1 : 1),
)

$("[ui-jq]").each(function () {
  let options = $(this).attr('ui-options').replace('{', '').replace('}', '').split('\n')

  let o = {}
  options.filter(function(option) { return ! option.match(/^\s*$/) }).forEach(function(option){
      option = option.trim().replace(/,$/, '')
      let a = option.split(/: /)
      o[a[0]] = a[1].replace("'", '')
  })
  console.info(sortObjectByKeys(o))
});
</script>
<script src = "https://code.jquery.com/jquery-3.6.3.js" integrity = "sha256-nQLuAZGRRcILA+6dMBOvcRh5Pe310sBpanc6+QBmyVM = " crossorigin = "anonymous"></script>

<div ui-jq = "easyPieChart"
     ui-options = "{
                 percent: 75,
                 lineWidth: 5,
                 trackColor: '#e8eff0',
                 barColor: '#23b7e5',
                 scaleColor: false,
                 color: '#3a3f51',
                 size: 134,
                 lineCap: 'butt',
                 rotate: -90,
                 animate: 1000
                 }"
     class = "easyPieChart">
</div>
Ответ принят как подходящий

Вы можете использовать JSON.parse():

const opts=$("[ui-jq]").get().map(el=>Object.fromEntries(Object.entries(JSON.parse(el.getAttribute('ui-options').replaceAll("'",'"').replace(/(\w+)(?=\s*:)/g,'"$1"'))).sort(([a],[b])=>a.localeCompare(b))));
console.info(opts);
<script src = "https://code.jquery.com/jquery-3.6.3.js" integrity = "sha256-nQLuAZGRRcILA+6dMBOvcRh5Pe310sBpanc6+QBmyVM = " crossorigin = "anonymous"></script>

<div ui-jq = "easyPieChart"
     ui-options = "{
                 percent: 75,
                 lineWidth: 5,
                 trackColor: '#e8eff0',
                 barColor: '#23b7e5',
                 scaleColor: false,
                 color: '#3a3f51',
                 size: 134,
                 lineCap: 'butt',
                 rotate: -90,
                 animate: 1000
                 }"
     class = "easyPieChart">
</div>

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

kmoser 27.12.2022 21:42

Хорошо, я добавил сортировку. Не понимал, что это важно здесь.

Carsten Massmann 27.12.2022 21:56

@kmoser Вы не должны полагаться на порядок ключей в объекте

Bergi 27.12.2022 22:54

@Bergi Это сложный вопрос, и на него есть несколько ответов в зависимости от того, как вы собираетесь использовать объект.

kmoser 28.12.2022 01:43

@kmoser Это сложно только тогда, когда вам нужно это сделать. Общий совет, что вам не следует этого делать, остается в силе.

Bergi 28.12.2022 01:46

Другие вопросы по теме