如何使用 Google Bigquery 的 Java API 以 Json 形式获取查询结果

Posted

技术标签:

【中文标题】如何使用 Google Bigquery 的 Java API 以 Json 形式获取查询结果【英文标题】:How to get query result in Json form using Java API of Google Bigquery 【发布时间】:2017-05-24 05:56:26 【问题描述】:

我正在使用 Google Bigquery V2 Java API。我无法找到以 JSON 格式获取查询结果的方法。 在 Bigquery Web UI 中,我们可以看到这种 JSON 和表格形式的结果。见截图。

有没有办法使用 Java API 将 GetQueryResultsResponse 作为 JSON。

【问题讨论】:

【参考方案1】:

一种选择是将TO_JSON_STRING function 应用于查询结果。例如,

#standardSQL
SELECT TO_JSON_STRING(t)
FROM (
  SELECT x, y
  FROM YourTable
  WHERE z = 10
) AS t;

如果您希望表格的所有列都为 JSON,您可以使用更简单的形式:

#standardSQL
SELECT TO_JSON_STRING(t)
FROM YourTable AS t
WHERE z = 10;

【讨论】:

这并不能解决我的问题。我们可以使用 JAVA API 获取 JSON 格式的查询结果吗?? Google 如何在 Web UI 上显示 JSON 结果。它是否将结果响应显式转换为 JSON 格式? 你能描述一下为什么这不能解决你的问题吗?客户端库从 BigQuery 服务获取 JSON 响应,并将它们转换为每种语言(Java、Python 等)的本机表示。如果你想要结果为 JSON 字符串,你可以使用这个函数。 我在 API 级别工作。对我来说,我无法更改用户的查询或不想强制用户使用 TO_JSON_STRING 函数。有没有办法将响应的本机表示转换为 JSON 字符串。类似于 Bigquery Web UI。 我也有同样的问题。我也想避免使用 TO_JSON_STRING 函数,因为我不仅要修改原始 SQL,而且这个函数的 json 输出格式与导出表的 json 输出格式不同。命令bq query --format json --project_id myProject "select * from sandbox.keweiquerytable"可以查询一个表,结果为json格式。所以我想应该有一种方法可以在 REST 或 JAVA API 中做到这一点。有人知道吗?【参考方案2】:

我正在使用服务帐号访问 BigQuery REST API 以获取 JSON 格式的响应。

要使用服务帐户,您必须转到凭据 (https://console.cloud.google.com/apis/credentials) 并选择一个项目。

你会得到这样的下拉菜单:

为您的项目创建一个服务帐户并下载 JSON 格式的机密文件。将 JSON 文件保存在文件系统中并设置其路径。检查下图以设置文件路径:

所以,现在您要做的就是使用 JAVA 客户端 api 来使用 Big Query REST API。

这是我一直用于我的项目的一个简单解决方案。

package com.example.bigquery;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;

import org.apache.log4j.Logger;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpContent;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.io.CharStreams;

public class BigQueryDemo 

    private static final String QUERY_URL_FORMAT = "https://www.googleapis.com/bigquery/v2/projects/%s/queries" + "?access_token=%s";

    private static final String QUERY = "query";

    private static final String QUERY_HACKER_NEWS_COMMENTS = "SELECT * FROM [bigquery-public-data:hacker_news.comments] LIMIT 1000";

    private static final Logger logger = Logger.getLogger(BigQueryDemo.class);

    static GoogleCredential credential = null;
    static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    static final JsonFactory JSON_FACTORY = new JacksonFactory();
    static 
        // Authenticate requests using Google Application Default credentials.
        try 
            credential = GoogleCredential.getApplicationDefault();
            credential = credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/bigquery"));
            credential.refreshToken();
         catch (IOException e) 
            e.printStackTrace();
        
    

    public static void implicit() 
        String projectId = credential.getServiceAccountProjectId();
        String accessToken = generateAccessToken();
        // Set the content of the request.
        Dataset dataset = new Dataset().addLabel(QUERY, QUERY_HACKER_NEWS_COMMENTS);
        HttpContent content = new JsonHttpContent(JSON_FACTORY, dataset.getLabels());
        // Send the request to the BigQuery API.
        GenericUrl url = new GenericUrl(String.format(QUERY_URL_FORMAT, projectId, accessToken));
        logger.debug("URL: " + url.toString());
        String responseJson = getQueryResult(content, url);
        logger.debug(responseJson);
    

    private static String getQueryResult(HttpContent content, GenericUrl url) 
        String responseContent = null;
        HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory();
        HttpRequest request = null;
        try 
            request = requestFactory.buildPostRequest(url, content);
            request.setParser(JSON_FACTORY.createJsonObjectParser());
            request.setHeaders(
                    new HttpHeaders().set("X-HTTP-Method-Override", "POST").setContentType("application/json"));
            HttpResponse response = request.execute();
            InputStream is = response.getContent();
            responseContent = CharStreams.toString(new InputStreamReader(is));
         catch (IOException e) 
            logger.error(e);
        
        return responseContent;
    

    private static String generateAccessToken() 
        String accessToken = null;
        if ((System.currentTimeMillis() > credential.getExpirationTimeMilliseconds())) 
            accessToken = credential.getRefreshToken();
         else 
            accessToken = credential.getAccessToken();
        
        System.out.println(accessToken);
        return accessToken;
    

以下是代码的 Github 链接:https://github.com/vslala/BigQueryRestSample

这只是一个从 BQ REST API 获取 JSON 数据的演示项目。不要直接在你的项目中使用它。 如果您有任何问题,请告诉我。

【讨论】:

以上是关于如何使用 Google Bigquery 的 Java API 以 Json 形式获取查询结果的主要内容,如果未能解决你的问题,请参考以下文章

google-bigquery 如何使用 https 获取数据集列表?

在 Google 表格中使用 BigQuery,如何授予其他用户按“刷新”的权限?

如何使用 AppScript 在 BigQuery 中将 Google 工作表持久化为表格

如何使用 Google Natural Language API 丰富 Bigquery 表中的数据?

如何使用 Bigquery 在 Google Bigquery 中进行身份验证,而无需使用服务帐户进行用户输入

在 google bigquery 中,如何使用 google python 客户端使用 javascript UDF