private Change readChangeObject(JSONObject jsonChange) throws JSONException {

    JSONObject jsonFieldsChanged = jsonChange.getJSONObject("fields_changed");
    List<FieldChange> fieldChanges = Lists.<Change.FieldChange>newArrayList();

    for (Field field : Field.values()) {

      if (!jsonFieldsChanged.has(field.toString())) continue;

      JSONObject jsonFieldChange = jsonFieldsChanged.getJSONObject(field.toString());

      switch (field) {
        case bugs_closed:
          String newBugs = CSV_JOINER.join(readStringArray(jsonFieldChange, "added"));
          String oldBugs = CSV_JOINER.join(readStringArray(jsonFieldChange, "removed"));

          fieldChanges.add(new FieldChange(field, null, newBugs, oldBugs, null, null));
          break;

        case diff:
          JSONObject addedDiff = jsonFieldChange.getJSONObject("added");

          fieldChanges.add(
              new FieldChange(
                  field,
                  new ObjectLink(addedDiff.getInt("id"), Diff.class),
                  null,
                  null,
                  null,
                  null));
          break;

          // TODO unhandled
        case screenshots:
        case file_attachments:
        case target_groups:
        case target_people:
          continue;

        case status:
          fieldChanges.add(
              new FieldChange(
                  field,
                  null,
                  ReviewRequestStatus.parseStatus(jsonFieldChange.getString("new")).toString(),
                  ReviewRequestStatus.parseStatus(jsonFieldChange.getString("old")).toString(),
                  null,
                  null));
          break;

        case summary:
        case description:
        case testing_done:
        case branch:
          fieldChanges.add(
              new FieldChange(
                  field,
                  null,
                  jsonFieldChange.getString("new"),
                  jsonFieldChange.getString("old"),
                  null,
                  null));
          break;

        default:
          ReviewboardCorePlugin.getDefault()
              .log(
                  IStatus.WARNING,
                  "Could not parse change due to unhandled field with name " + field.toString());
          continue;
      }
    }

    return new Change(
        jsonChange.getInt("id"),
        jsonChange.getString("text"),
        ReviewboardUtil.marshallDate(jsonChange.getString("timestamp")),
        fieldChanges);
  }