从JSON属性中移除双引号

3

我正在尝试使用hopscotch.js创建交互式旅游。JavaScript库要求旅游的标准数据结构如下:

// Define the tour!
    var tour = {
      id: "hello-hopscotch",
      steps: [
        {
          title: "My Header",
          content: "This is the header of my page.",
          target: "header",
          placement: "right"
        },
        {
          title: "My content",
          content: "Here is where I put my content.",
          target: document.querySelector("#content p"),
          placement: "bottom"
        }
      ]
    };

将旅游步骤直接放入JavaScript库中是完全可行的,但理想情况下,我希望能够将所有这些细节保存在数据库中,并使用AJAX将数据传递到hopscotch.js。(这样可以动态创建旅游路线,并且可以在不发布代码的情况下更改content)。除了当我的target使用document.querySelector()元素选择器时,一切都运作良好。每个旅游步骤的基本C#模型如下:
public class MockTourSteps
{
    public string Title { get; set; }
    public string Content { get; set; }
    public string Target { get; set; }
    public string Placement { get; set; }
}

由于 Target 是一个字符串,因此我必须使用双引号传递该值。
问题在于,当它被序列化为JSON时,在使用Chrome开发者工具查看页面时,会出现以下错误: 语法错误,无法识别的表达式:document.querySelector(“。btn-primary”) 通过探索返回到页面的JSON数据,我可以看到围绕我的 document.querySelector()的双引号正在引起问题。
当我通过 document.querySelector()指定 target 时,需要将这些双引号从 target 中删除,但是当我基于HTML标记(例如 header )指定 target 时,双引号应保留。
有什么想法如何实现这一点吗?

你尝试过使用JSON.stringify将JavaScript值转换为JSON字符串吗?https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify - man_luck
在上面的 JavaScript 代码中,你实际上是将 document.querySelector() 的结果作为 target 的值传递,这真的是你想要的吗? - DavidG
@Stu1986C:(删除的评论建议在querySelector调用中使用单引号)。 querySelector的参数只需要由JS解释,对于C#而言,它只是字符串的一部分;因此,服务器端语法没有问题。但是,您需要在JS端检测到字符串化的函数调用(很容易),并执行(仍然很容易,但这涉及到我所知道的不鼓励使用eval)。 - collapsar
@collapsar 我想我明白你的意思(如果我理解错误请见谅)。问题不仅在于我传递给 querySelector 的参数是一个字符串...而且 document.querySelector() 本身也是一个字符串。这是因为我在 MockTourSteps 模型中的 Target 属性是字符串类型。我需要保持这个字段的灵活性,以便我可以将诸如“footer”之类的字符串传递到 target 字段中,供 hopscotch.js 使用。 - Stu1986C
1
@Stu1986C 我理解了这一点,也没有找到其他替代方案,只能使用 JavaScript 的 eval - collapsar
显示剩余3条评论
1个回答

1
在提供的示例中,主要问题是您正在使用JavaScript对象,但您将从服务器获取JSON。 您需要在客户端使用某种JSON处理方式。
我认为您可以在模型中添加更多信息:
public class MockTourStep
{
    public string Title { get; set; }
    public string Content { get; set; }
    public TargetC Target { get; set; }
    public string Placement { get; set; }

    public enum TargetType
    {
        ElementName,
        QuerySelector
    }

    public class TargetC
    {
        [JsonConverter(typeof(StringEnumConverter))]
        public TargetType Type { get; set; }

        public string Value { get; set; } 
    }
}

和样本响应:

var tour = new
{
    Id = "hello-hopscotch",
    Steps = new List<MockTourStep>
    {
        new MockTourStep
        {
            Title = "My Header",
            Content = "This is the header of my page.",
            Target = new MockTourStep.TargetC
            {
                Type = MockTourStep.TargetType.ElementName,
                Value = "header"
            },
            Placement = "bottom"
        },
        new MockTourStep
        {
            Title = "My content",
            Content = "Here is where I put my content.",
            Target = new MockTourStep.TargetC
            {
                Type = MockTourStep.TargetType.QuerySelector,
                Value = "document.querySelector('#content p')"
            },
            Placement = "bottom"
        }
    }
};

然后,在客户端,您可以检查目标类型并将其设置为有效值:

$.getJSON("url", function (tour) {
    for (var i = 0; i < tour.steps.length; i++) {
        var step = tour.steps[i];

        switch (step.target.type) {
            case "ElementName":
                step.target = step.target.value;
                break;
            case "QuerySelector":
                step.target = eval(step.target.value);
                break;
            default:
                throw Error;
        }
    }

    hopscotch.startTour(tour);
});

请注意,在使用 QuerySelector 时可能会使用到 eval。然而,使用 eval 是危险的,因此您需要检查您向客户端提供的内容。

谢谢Aleksandr。这个逻辑对我来说很有意义。我会尽快尝试并告诉你它是否适用于我 :) - Stu1986C
成功了。谢谢Aleksandr!我只需要更改你的代码中的switch语句,用它们各自的枚举整数替换字符串即可。 - Stu1986C
请注意,我使用 JsonConverter(typeof(StringEnumConverter)) 属性。在这种情况下,枚举值将被序列化为字符串表示形式。 - Aleksandr Ivanov
这很奇怪,因为在我的测试项目中它是可以工作的。我认为你应该尝试手动序列化你的模型来进行测试。 - Aleksandr Ivanov
您还可以查看此问题的最高票答案。 - Aleksandr Ivanov
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接