【问题标题】:google closure compiler and json谷歌闭包编译器和 json
【发布时间】:2012-03-12 23:28:05
【问题描述】:

我有一个我解析的 json 字符串,然后使用点符号访问对象的属性。但是,在 google 闭包编译器中,点表示法 (MyObject.PropertyName) 会发出未定义属性的警告。

目前,我使用的解决方案是将我的代码转换为括号表示法 (MyObject['PropertyName'])。这消除了警告,但也阻止了编译器完成它的工作。另一方面,当我写JSON.stringify(MyObject) 时,服务器会收到一个字符串,其中的属性名称是可以理解的。

所以我的问题是,在处理运行时反序列化和序列化的 json 对象时,我们如何最好地在高级模式下使用 google 编译器。

【问题讨论】:

    标签: javascript json google-closure-compiler


    【解决方案1】:

    你基本上有两种选择:

    1. 使用字符串文字(又名MyJsonObject['PropertyName'])使用对象数组访问,这是简单的解决方案。
    2. 创建一个描述 JSON 对象属性的外部文件,然后使用点表示法(又名MyJsonObject.PropertyName)。这需要更多维护,但如果您在外部描述中提供类型注释,则允许编译器对属性进行类型检查。

    【讨论】:

    【解决方案2】:

    如果您要编写的唯一 JavaScript 是访问外部 json,那么它就失去了使用编译器的意义。但是,如果除了将 json 解析为域模型之外,您还有少量的 JavaScript 也能正常工作,那么编译器可能会很有用。

    在我们的解析器中,我们通过括号符号访问我们的数据,因此我们可以正确获取数据。从那里我们将数据填充到我们自己的模型中,我们使用 .上的符号。这些被广泛重命名,为我们提供类型检查和所有这些好处。

    编辑>> 对于数据,我使用XHRManager。这是一堂非常好的课。当我从该池中获取数据事件时,我会按如下方式处理它。

    /**
     * @private
     * @param {goog.events.Event} evt The event recieved from the XhrIo.
     */
    mypath.MyClass.prototype.onDataRecieved_ = function(evt) {
      if (evt.type != 'complete') return;
      var xhrIo = evt.target;
      var data = xhrIo.getResponseJson();
      //do somethign!
    };
    

    我必须警告你,我的 XHRManager 处理仍然有很多不足之处。我上周才重构了我的代码以开始使用它。

    为了解析,我这样做:(这是我代码库中的一些原始内容,所以忽略一些丑陋的东西。)

    our.class.path.ContestJsonParser.prototype.setContestProperties =
        function(contest, element) {
      contest.setName(element['description']);
      /**
         * @type {!number}
         */
      var timeAsInt = element['startTime'];
      contest.setScheduledStartTime(timeAsInt);
      var clockModel = contest.getClockModel();
      if (goog.isDefAndNotNull(element['period'])) {
        clockModel.setMatchState(element['period']['periodName']);
        clockModel.setStateStartTime(element['period']['periodStartTime']);
      }
      //TODO (Johan) this needs to change today to consider the rest of the stats
      //information
      var stats = element['statistics'];
      if (goog.isObject(stats) && goog.isDefAndNotNull(stats['score'])) {
        var score = stats['score'];
        contest.setMatchScore(score['home'], score['away']);
      } else {
        contest.setMatchScore(undefined, undefined); // clears score.
      }
    };
    

    【讨论】:

    • 您是否经常通过 json.stringify 和 json.parse 序列化您的数据?这是非常低效的,你这样做的原因是什么。脱离上下文我的代码对你来说没有多大意义,但我们使用构建器模式en.wikipedia.org/wiki/Builder_pattern 将模型创建与解析分开。老实说,我认为您的问题的核心可能是您对 stringify + parse 的使用,向我解释一下您打算用这个解决什么。
    • 是的,我使用本机序列化程序。有什么更好的选择?我在某处读到使用库比使用本机解析要慢。对象通过 ajax 进出并进出本地存储。
    • 我刚刚修改了我的评论,再次检查并向我解释为什么您一直使用 Json.stringify 和 Json.parse。
    • 你如何处理ajax中的传输?在某些时候,数据在 json 中,所以目前,我必须解析字符串。如果你能用一些代码展示避免 JSON.parse 时的样子,我会很好;即使对于只有 2 个属性的对象。没有很好的解释如何一起使用 typedef 和 json 解析。
    • 好的,代码中的哪里是从通用 json 对象到具有类型定义的 javascript 对象的转换?
    【解决方案3】:

    编辑:@expose 指令已被弃用


    Google Closure Compiler 可让您指定关于如何通过注解进行编译的指令。

    见: https://developers.google.com/closure/compiler/docs/js-for-compiler

    正确使用 @expose@type 可以保留 代码中的一个属性。

    可以安全地将 JSON 字符串解码为对象,并且 使用点符号访问该对象。您还可以 将数据字符串化。

    -

    我们举个例子:

    你想解析一个对象数组。每个对象代表一个 "size",属性 w 表示宽度,h 表示高度。

    size 对象声明一个原型并公开它 属性 wh

    function size() {}
    
    /** @expose */
    size.prototype.w = 0;
    /** @expose */
    size.prototype.h = 0;
    

    然后你想把 JSON 解析后的数据放入一个名为的数组中 数据

    使用 @type 声明 data 将持有 大小类型的对象的数组

    function main()
    {
        /** @type {Array.<size>} */
        var data;
    
        // string built up just for example purposes
        var response = '[{"w": 10, "h": 20}]';
    
        // parse the array
        var data = JSON.parse(response);
    
        // access data with dot notation!
        console.log(data[0].w+ "    "+ data[0].h);
    }
    
    main();
    

    【讨论】:

    • 我在您指向的网页上找不到任何提及@expose。此注释是否记录在某处?
    • @jochen @expose 指令已从文档中删除。令人惊讶的是,它甚至没有被提及为已弃用。现在看来@expose 只出现在一些 SO 答案上,比如我的。我想它仍然受支持以避免破坏遗留代码,但我没有检查。我仍在使用旧版本的 Closure 编译器(从 @expose 开始记录和实施)
    • @expose 现已正式弃用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    相关资源
    最近更新 更多