【问题标题】:Updating JSON key value from an array by index按索引从数组中更新 JSON 键值
【发布时间】:2019-02-16 17:05:32
【问题描述】:

我正在使用 Angular javascript 来完成一项任务,我需要在点击函数时从数组中更新 JSON 键值。

我有这样的 JSON 结构:-

$scope.jsonObj = {
    "stylesheet": {
        "attribute-set": [{
                "attribute": {
                    "_name": "text-align",
                    "__prefix": "xsl",
                    "__text": "center"
                },
                "_name": "__frontmatter",
                "__prefix": "xsl"
            },
            {
                "attribute": [{
                        "_name": "space-before",
                        "__prefix": "xsl",
                        "__text": "80mm"
                    },
                    {
                        "_name": "line-height",
                        "__prefix": "xsl",
                        "__text": "140%"
                    }
                ],
                "_name": "__frontmatter__title",
                "_use-attribute-sets": "common.title",
                "__prefix": "xsl"
            }
        ],
        "_version": "2.0",
        "__prefix": "xsl"
    }
};

我有一个数组 $scope.textvalue=["center", "80mm","150%"] 。所以这里我要根据索引更新JSON的键值__text。表示我想根据 JSON 和数组中__text 的索引推送数组详细信息。

我在 controller 中单击按钮时执行此操作。

$scope.save = function(index) {
    $scope.textvalue[index];
    console.log($scope.textvalue);
    $scope.objIndex = $scope.jsonObj.findIndex((obj => obj.__text));
    console.log("Before update: ", $scope.jsonObj[$scope.objIndex]);
    $scope.jsonObj[$scope.objIndex].__text = ? ? ? ;
    console.log("After update: ", $scope.jsonObj[$scope.objIndex]);
}

我做了$scope.jsonObj[$scope.objIndex].__text = ???;因为我不知道该怎么做,我有一个错误,因为 $scope.jsonObj.findIndex is not a function

建议我用一些方法来更新我的 JSON 值。

【问题讨论】:

  • 使用 jsonObj.stylesheet['attribute-set'] 更新值
  • @HimanshuShekhar 我在这里怎么办$scope.jsonObj[$scope.objIndex].__text = ? ? ? ;我没听懂你

标签: javascript arrays angularjs loops object


【解决方案1】:

您可以通过使用 Array.forEach() method 迭代 $scope.jsonObj.stylesheet["attribute-set"] 数组并分别为每个 attribute 对象/数组更新相关的 "__text" 属性来实现。

  • 我使用 Array#isArray() method 来检查迭代的attribute 属性是array 还是object
  • 我将$scope.textvalue 数组复制到arr 并使用 Array#shift() method 在每次迭代中从arr 数组中获取相关值。

这应该是你的代码:

const arr = $scope.textvalue.slice();
$scope.jsonObj.stylesheet["attribute-set"].forEach(function(a) {
  if (Array.isArray(a.attribute)) {
    a.attribute.forEach(att => att["__text"] = arr.shift());
  } else {
    a.attribute["__text"] = arr.shift();
  }
});

演示:

$scope= {};
$scope.jsonObj = {
  "stylesheet": {
    "attribute-set": [{
        "attribute": {
          "_name": "text-align",
          "__prefix": "xsl",
          "__text": "center"
        },
        "_name": "__frontmatter",
        "__prefix": "xsl"
      },
      {
        "attribute": [{
            "_name": "space-before",
            "__prefix": "xsl",
            "__text": "80mm"
          },
          {
            "_name": "line-height",
            "__prefix": "xsl",
            "__text": "140%"
          }
        ],
        "_name": "__frontmatter__title",
        "_use-attribute-sets": "common.title",
        "__prefix": "xsl"
      }
    ],
    "_version": "2.0",
    "__prefix": "xsl"
  }
};

$scope.textvalue = ["center", "80mm", "150%"];
const arr = $scope.textvalue.slice();

$scope.jsonObj.stylesheet["attribute-set"].forEach(function(a) {
  if (Array.isArray(a.attribute)) {
    a.attribute.forEach(att => att["__text"] = arr.shift());
  } else {
    a.attribute["__text"] = arr.shift();
  }
});
console.log($scope.jsonObj);

【讨论】:

  • @tanmay 是的,我刚刚注意到这一点,但它在这种情况下有效,无论如何我用解决方案更新了答案。
  • 我越来越不确定
  • @WhoAmI 你在哪里得到undefined,在哪个属性?你添加了const arr = $scope.textvalue;这一行吗?
  • 是的,我已经添加了,我创建了一个新对象$scope.newJson =$scope.jsonObj.stylesheet["attribute-set"].forEach(function(a) { .... 并得到了安慰
  • @tanmay no no ,我可以根据输入字段更改任何值。所有都在 ng-repeat 按索引。
【解决方案2】:

我会这样做。我创建了一个像你一样的函数(除了它现在不在 AngularJS 中,但你可以很容易地实现它)。

您将索引传递给函数,它将遍历__text 的出现并找出将值放在哪里。

这是有效的 sn-p:(当我通过相应的索引时,请参阅最后/第三个 __text 值中的 150%

let jsonObj = {
  "stylesheet": {
    "attribute-set": [{
        "attribute": {
          "_name": "text-align",
          "__prefix": "xsl",
          "__text": "center"
        },
        "_name": "__frontmatter",
        "__prefix": "xsl"
      },
      {
        "attribute": [{
            "_name": "space-before",
            "__prefix": "xsl",
            "__text": "80mm"
          },
          {
            "_name": "line-height",
            "__prefix": "xsl",
            "__text": "140%"
          }
        ],
        "_name": "__frontmatter__title",
        "_use-attribute-sets": "common.title",
        "__prefix": "xsl"
      }
    ],
    "_version": "2.0",
    "__prefix": "xsl"
  }
};

let textvalue = ["center", "80mm", "150%"];

let textvalueIndex = 0;

function save(index) {
  let updated = jsonObj.stylesheet['attribute-set'].reduce(function(agg, obj) {
    if (Array.isArray(obj.attribute)) {
      for (let i = 0; i < obj.attribute.length; i++) {
        if (textvalueIndex === index) {
          obj.attribute[i].__text = textvalue[textvalueIndex];
        }
        textvalueIndex++;
      }
    } else {
      if (textvalueIndex === index) {
        obj.attribute.__text = textvalue[textvalueIndex];
      }
      textvalueIndex++;
    }
    agg.push(obj);
    return agg;
  }, [])

  console.log(updated)
}

save(2) // third item in textvalue array will be saved on the third occurance of __text

【讨论】:

  • 谢谢 Tanmay 让我明白这一点,然后我会告诉你的。
  • @WhoAmI 当然,如果您遇到任何问题,请告诉我
【解决方案3】:

主要问题是attribute 可以是对象字面量,也可以是对象字面量数组。这是一个通过比较__text 并返回对相关属性的引用来遍历 jsonObj 的函数。如果没有找到,则会添加并返回一个新属性:

function getAttribute(__text) {
  var attributes = $scope.jsonObj['stylesheet']['attribute-set']; 
  for (var i=0, l=attributes.length; i<l; i++) {
    var attribute = attributes[i].attribute;
    if (attribute.length) {  //array of attributes
       for (attr in attribute) {
         if (attribute[attr].__text == __text) return attribute[attr]
       }
    } else {  //attribute literal
      if (attribute.__text == __text) return attribute
    } 
  }
  var index = attributes.push({  
    attribute: { __text: __text } 
  });
  return attributes[i].attribute
}

示例:

var center = getAttribute('center');
center.NEW_VALUE = 'TEST';

var new_attr = getAttribute('new_attr');
new_attr.__prefix = 'SOMETHING';  

【讨论】:

  • 是的,确实如此。不是创建新属性会改变结构。我可能错了。让我试试。谢谢
  • @WhoAmI,是的,它会通过使用新属性扩展attribute-set 来改变结构,这可能没有必要,只是认为如果属性(或__text)无法使用则需要后备' 被发现。
  • 我很困惑为什么你不想寻找__name,但如果你想在任何地方将__text 更改为__name。这样你就可以做到var attr = getAttribute('space-before'); item.__text = '120mm';
  • 感谢您的信息,您说得对,我必须通过名称更改文本。
猜你喜欢
  • 1970-01-01
  • 2023-02-24
  • 2021-03-10
  • 2015-01-20
  • 1970-01-01
  • 2019-08-25
  • 1970-01-01
  • 1970-01-01
  • 2022-07-07
相关资源
最近更新 更多