谷歌闭包编译器和JSON

11

我有一个Json字符串,我解析它并使用点号符号访问对象的属性。然而,在谷歌闭包编译器中,点号符号(MyObject.PropertyName)会出现未定义属性的警告。

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

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

3个回答

5

你基本上有两种选择:

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

你有哪些资源可以提供给我,以便了解如何指定 externs 文件?谢谢! - Ming K
1
通常,externs必须是有效的JavaScript,但是简化的声明: var - John

2
如果你要编写的唯一 JavaScript 是访问外部 json,那么使用编译器就失去了意义。然而,如果你有即使是微不足道的 JavaScript 除了将 json 解析为域模型之外的工作,那么编译器可能会有用。
在我们的解析器中,我们通过方括号表示法访问数据,以便正确获取数据。从那里,我们将数据放入自己的模型中,使用 . 表示法。这些名称被广泛重命名,给我们提供了类型检查和所有这些好处。
编辑 >> 对于数据,我使用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序列化数据?这是极其低效的,你这样做的原因是什么?我的代码如果没有上下文可能不太容易理解,但我们使用建造者模式(http://en.wikipedia.org/wiki/Builder_pattern)将模型创建与解析分离。我真诚地认为你问题的核心可能是你使用stringify + parse,告诉我你想通过这种方式解决什么问题。 - lennel
是的,我使用本地序列化程序。有更好的选择吗?我在某个地方读到,使用库比使用本地解析慢。这些对象通过ajax来回传递,并存储在本地存储中。 - frenchie
我刚刚修改了我的评论,请再次检查并解释一下为什么你一直使用Json.stringify和Json.parse。 - lennel
你如何处理ajax中的传输?在某些情况下,数据以json格式存在,因此目前我必须解析字符串。如果您能用一些代码展示避免使用JSON.parse的情况,即使是仅有2个属性的对象,那将非常好。关于如何同时使用typedef和json解析,没有很好的解释。 - frenchie
好的,在代码中从通用的JSON对象转换为具有类型定义的JavaScript对象的操作在哪里? - frenchie
显示剩余3条评论

2

编辑:@expose指令已被弃用。


Google Closure Compiler lets you specify directives on how compilation should be done through annotations.

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

Properly using @expose and @type you can preserve the name of a property in your code.

It is possible to safely decode a JSON string into an object and access that object using the dot notation. You'll be also able to stringify back the data.

-

Let's make an example:

You want to parse an array of objects. Every object represents a "size", with the properties w for width and h for height.

Declare a prototype for the size object and expose its properties w and h

function size() {}

/** @expose */
size.prototype.w = 0;
/** @expose */
size.prototype.h = 0;

Then you want to put the JSON parsed data into an array called data.

Using @type you declare that data is going to hold an array of object of type size.

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
@jochen,“@expose”指令已从文档中删除。令人惊讶的是,它甚至没有被标记为弃用。现在,“@expose”似乎只出现在一些SO答案中,比如我的答案。我猜它仍然受支持以避免破坏旧代码,但我没有检查。我仍在使用旧版本的Closure编译器(来自实施“@expose”的时间)。 - Paolo
@expose现已正式弃用。 - Chad Killingsworth

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