【问题标题】:IllegalStateException when trying to return a JSON object from an Azure Mobile Services script尝试从 Azure 移动服务脚本返回 JSON 对象时出现 IllegalStateException
【发布时间】:2014-04-27 07:31:30
【问题描述】:

我已经修改了 Azure 移动服务中我的一个表的更新脚本,以接收一个包含一组对象的对象,并使用 MSSQL 对象更新与这些对象相关的 SQL 记录。效果很好,但我希望我的更新脚本将更新的对象列表返回给客户端。问题是我似乎无法将 JSON 对象返回给客户端并将其反序列化为正确的 StoryList 对象,而不会在客户端上遇到“com.google.gson.JsonSyntaxException:java.lang.IllegalStateException”。

我花了几个小时试图弄清楚这一点,但仍然不知道我在这里做错了什么。我错过了什么吗?

编辑:这是客户端阻塞的 JSON:

{"id":"arandomid",
 "stories":
[
{"id":"7EC413C3-17A8-410A-A394-ABF334364226",
"__createdAt":"2014-03-31T22:22:14.398Z",
"__updatedAt":"2014-04-28T01:43:27.484Z",
"__version":"AAAAAAAACf4=",
"title":"remove a user story",
"relativepriority":11,
"estimate":7,
"assignedto":"David",
"sprintid":"E51B4E0D-23C7-4695-BD9B-71E34A0BF5B5",
"sprintphase":1},

{"id":"99890AFE-13C2-4E1A-8376-B501CB07080D",
"__createdAt":"2014-03-31T22:26:35.160Z",
"__updatedAt":"2014-04-28T01:43:27.484Z",
"__version":"AAAAAAAACf0=",
"title":"view user story list",
"relativepriority":10,
"estimate":15,
"assignedto":"Michael",
"sprintid":"E51B4E0D-23C7-4695-BD9B-71E34A0BF5B5",
"sprintphase":1}
]
}

这里是更新脚本:

var storiesToUpdate;
var returnItem;
function update(item, user, request) {
    returnItem = item;
    storiesToUpdate = JSON.parse(item.stories);
    if(storiesToUpdate.length > 0){
       var sql = "UPDATE UserStory SET relativepriority = CASE id ";
       for(var i = 0; i < storiesToUpdate.length; ++i){
          sql+= ("WHEN '" + storiesToUpdate[i].id + "' THEN " + storiesToUpdate[i].relativepriority + " "); 
       }
       sql+="END ";
       sql+="WHERE ";
       for(var i = 0; i < storiesToUpdate.length; ++i){
          if(i > 0) sql+= "OR ";
          sql+= ("(id = '" + storiesToUpdate[i].id + "') "); 
       }

       mssql.query(sql,{
           success: function(connection){
                var sql2 = 'SELECT * from UserStory '
                sql2+="WHERE ";
                for(var i = 0; i < storiesToUpdate.length; ++i){
                   if(i > 0) sql2+= "OR ";
                   sql2+= ("(id = '" + storiesToUpdate[i].id + "') "); 
                }
                mssql.query(sql2,{
                    success:function(results){
                        console.log("results: " + results);
                        var returnObject = {};
                        returnObject["id"]="arandomid";
                        returnObject["stories"]=results;
                        console.log("return object: " + returnObject);
                        request.respond(statusCodes.OK, returnObject);
                    },
                    error: function(err){
                        console.log("Update ok, but subsequent read failed: " + err);
                        request.respond(err);
                    }
                });
           },
           error: function(err) {
               console.log("fail on open: " + err);
               request.respond(err);
           }
       });
    }
    else{
          request.respond();
        }
}

这是在 Android 应用中被序列化/反序列化的类:

public class StoryList {

    @com.google.gson.annotations.SerializedName("id")
    private String mId;

    @com.google.gson.annotations.SerializedName("stories")
    ArrayList<UserStory> mStories;

    public StoryList(){

    }

    public String getId() {
        return mId;
    }

    public final void setId(String id) {
        mId = id;
    }

    public void setStories(ArrayList<UserStory> stories){
        this.mStories = stories;
    }

    public ArrayList<UserStory> getStories(){
        return mStories;
    }
}

这是我注册的 CollectionSerializer 类,用于在单个查询中发送并希望返回对象集合:

public class CollectionSerializer<E> implements
JsonSerializer<Collection<E>>, JsonDeserializer<Collection<E>>{

    public JsonElement serialize(Collection<E> collection, Type type,
            JsonSerializationContext context) {
        JsonArray result = new JsonArray();
        for(E item : collection){
            result.add(context.serialize(item));
        }
        JsonPrimitive retVal = new JsonPrimitive(result.toString());
        Log.i("CollectionSerializer.Serialize", retVal.getAsString());
        return retVal;
    }


    @SuppressWarnings("unchecked")
    public Collection<E> deserialize(JsonElement element, Type type,
            JsonDeserializationContext context) throws JsonParseException {
         Log.i("CollectionSerializer.Deserialize", element.getAsString());
         JsonArray items = (JsonArray) new JsonParser().parse(element.getAsString());
         ParameterizedType deserializationCollection = ((ParameterizedType) type);
         Type collectionItemType = deserializationCollection.getActualTypeArguments()[0];
        Collection<E> list = null;

        try {
            list = (Collection<E>)((Class<?>) deserializationCollection.getRawType()).newInstance();
            for(JsonElement e : items){
                list.add((E)context.deserialize(e, collectionItemType));
            }
        } catch (InstantiationException e) {
            throw new JsonParseException(e);
        } catch (IllegalAccessException e) {
            throw new JsonParseException(e);
        }

        return list;
    }
}

最后,这里是我实际启动查询以进行更新的地方:

@Override
public void onStoryListReorder(int phaseNumber){
    float newRelPriority = 10;
    ArrayList<UserStory> phaseStoryList = mPhaseStories.get(phaseNumber);

    for (UserStory s : phaseStoryList){
        s.setRelativePriority(newRelPriority++);
    }

    StoryList storylist = new StoryList();
    storylist.setStories(phaseStoryList);
    storylist.setId("blahblahblah");
    MobileServiceTable<StoryList> storyListTable = mClient.getTable("UserStory",StoryList.class);
    storyListTable.update(storylist, new TableOperationCallback<StoryList>(){
        public void onCompleted(StoryList entity,
                Exception exception, 
                ServiceFilterResponse response){
            if (exception == null){             
                //This is where I want to update the client's list of stories to match Azure's list.
            }
            else {
                createAndShowDialog(exception, "Error on updating: "+exception.toString());
            }
        }
    });
}

【问题讨论】:

  • com.google.gson.JsonSyntaxException 当 Gson 尝试读取(或写入)格式错误的 JSON 元素时引发此异常
  • 对,但是我需要在我的脚本中做些什么不同的事情来使 JSON 不会出现格式错误?
  • 老实说...您在这里发布了很多代码...但没有一个真正让我们能够帮助您。只是看了一眼,尽管您似乎不太可能需要任何类型的自定义反序列化,而且您似乎只返回一个 JSON 对象,但正试图将其视为一个集合。首先发布一个返回到您的应用的 JSON 示例。
  • 是的,忘记包含 JSON 本身 :) 我刚刚添加了那个。请参阅我上面的编辑。关于 CollectionSerializer,它与这里建议的发送对象 ArrayList 的方式基本相同:hashtagfail.com/post/44606137082/…

标签: javascript android node.js gson azure-mobile-services


【解决方案1】:

我最终想通了。问题出在我对 ArrayList 的反序列化方法中。固定的反序列化方法如下。该方法的第一行解决了这个问题:

@SuppressWarnings("unchecked")
public Collection<E> deserialize(JsonElement element, Type type,
        JsonDeserializationContext context) throws JsonParseException {
    JsonArray items = element.getAsJsonArray();
    ParameterizedType deserializationCollection = ((ParameterizedType) type);
    Type collectionItemType = deserializationCollection.getActualTypeArguments()[0];
    Collection<E> list = null;

    try {
        list = (Collection<E>)((Class<?>) deserializationCollection.getRawType()).newInstance();
        for(JsonElement e : items){
            list.add((E)context.deserialize(e, collectionItemType));
        }
    } catch (InstantiationException e) {
        throw new JsonParseException(e);
    } catch (IllegalAccessException e) {
        throw new JsonParseException(e);
    }

    return list;
}

请记住,以防其他人在此处处理示例:http://hashtagfail.com/post/44606137082/mobile-services-android-serialization-gson

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多