如何在Android中解析换行符分隔的Json响应?

时间:2015-10-18 18:48:38

标签: java android json gson retrofit

NdJson数据的示例:

{"type":"data","id":"xyz"}
{"type":"value","id":"xcf"}
....
....

以下是我的RetrofitRxJava代码,可用于使用limit=1 {"type":"data","id":"xyz"}获取数据。

 adapter.create(API.class).getData()
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<APIData>() {
         @Override
         public void onCompleted() {}

         @Override
         public void onError(Throwable e) {}

         @Override
         public void onNext(APIData apidata) {}

         });

我的模型类

模型类只有两个参数:

public class APIData(){
  private String type;
  private String id;

  ..// Getter and setter for above two fields
}

Api类

public interface WarehouseAPI {
  @GET("/search?limit=1")
  public Observable<APIData> getdata ();
}

使用@GET("/search?limit=1")替换@GET("/search")时我遇到的错误是Malformed JSON: Syntax error

问题

如何正确解析NdJson

有没有办法将回复存储在List<APIData>

修改-1

现在我试图接受观察者中的通用Response

adapter.create(APIData.class).getdata()
       .subscribeOn(Schedulers.newThread())
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe(new Observer<Response>() {
        @Override
        public void onCompleted() {}

        @Override
        public void onNext(Response response) {}
 });

但获得no suitable method found for subscribe(<anonymous Observer<Response>>)

修改-2

但是,我正在做一些愚蠢的错误,我现在修复了“编辑-1”部分中出现的错误。现在我正在

Error:retrofit.RetrofitError: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 2 column 2 path $

3 个答案:

答案 0 :(得分:2)

我认为服务器响应具有以下格式

response.split("\n")

基本思想是从服务器接收响应作为字符串。将其拆分为replaceAll之类的数组。迭代一个Array,为每个数组元素创建一个新的json对象。

我确实意识到这很费时,正如你在评论中所描述的那样。您还可以尝试使用String String myResponse = "[" + response.replaceAll("/\n/", ",") + "]"; Gson gson = new Gson(); MyEntity[] arr = gson.fromJson(myResponse, MyEntity[].class); 方法将每行转换为数组元素并解析整个字符串。喜欢

Author.includes(:articles).where(:articles=>{published: true}).find(params[:author_id])

如果是改造。您将不得不使用自定义响应转换器。 我不会写出完整的解决方案,因为你已经找到了使用自定义Converter完成它的方法。

答案 1 :(得分:2)

为了让工作顺利,我必须通过Custom converter添加Retrofit.Converter工具:

public class CustomConverter implements Converter {

@Override
public Object fromBody(TypedInput body, Type type) throws ConversionException {
    String text = null;
    try {
        text = fromStream(body.in());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return text;

}

@Override
public TypedOutput toBody(Object object) {
    return null;
}

// Custom method to convert stream from request to string
public static String fromStream(InputStream in) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
    StringBuilder out = new StringBuilder();
    String newLine = System.getProperty("\n");
    String line;
    while ((line = reader.readLine()) != null) {
        out.append(line);
        out.append(newLine);
    }
    return out.toString();
}
}

它完美无缺!

答案 2 :(得分:1)

对于初学者来说,你的json不是Gson理解的json,所以你不能直接在Retrofit中使用Gson转换器。所以

public Observable<APIData> getdata ();

必须是

public Observable<Response> getdata ();

然后,你有

adapter.create(WarehouseAPI.class).getdata()
   .subscribeOn(Schedulers.newThread())
   .observeOn(AndroidSchedulers.mainThread())
   .map((Response res) -> new BufferedStreamReader(res.body.body().bytesStream()))
   .flatMap(stream -> {
       return Observable.create(subscriber -> {
           String line;
           while((line = stream.readLine() != null) {
               subscriber.onNext(gson.fromJson(line, APIData.class));
           }
           subscriber.onCompleted();
       });
   });

您可以订阅并接收您的json列表中的每个项目。

未经过测试,未处理错误案例(为简洁起见,未对订阅的有效性进行测试)。

尽管如此,它应该是正确的方向。