ブログサイトのロゴsui Tech Blog

Google Places API (New)で言語コードを設定せず沼りかけた

Google Places API (New)で言語コードを設定せず沼りかけた経験。

結論

  • 言語コードを設定する
  • 公式ドキュメントをしっかり読む

経緯

Next.jsでAPIからGoogle Places API (New)を叩こうとしたら、400番エラーになったので沼りかけた

実際にやったこと

curlでAPIを叩いたときの例が掲載されており、"X-Goog-Api-Key: API_KEY" のAPI_KEYを正しく設定すれば情報を取得できる。

次の例は、circle によって定義された、半径 500 m 以内のすべてのレストランの表示名に対する Nearby Search(New)リクエストを示しています。

curl -X POST -d '{
  "includedTypes": ["restaurant"],
  "maxResultCount": 10,
  "locationRestriction": {
    "circle": {
      "center": {
        "latitude": 37.7937,
        "longitude": -122.3965},
      "radius": 500.0
    }
  }
}' \
-H 'Content-Type: application/json' -H "X-Goog-Api-Key: API_KEY" \
-H "X-Goog-FieldMask: places.displayName" \
https://places.googleapis.com/v1/places:searchNearby

実際に同じようなことをやるAPIを作ってみる

import { NextResponse } from 'next/server';
import { config } from '@/lib/config';
import { LatLng } from '@/app/types';
 
export async function POST(req: Request) {
  if (req.method !== 'POST') {
    return NextResponse.json({ error: 'Method Not Allowed' }, { status: 405 });
  }
 
  try {
    const { lat, lng }: LatLng = await req.json();
 
    const apiKey = config.GOOGLE_MAPS_API_KEY;
    const apiUrl = 'https://places.googleapis.com/v1/places:searchNearby';
    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Goog-Api-Key': apiKey!,
        'X-Goog-FieldMask': 'places.displayName',
      },
      body: JSON.stringify({
        includedTypes: ['restaurant'],
        maxResultCount: 10,
        languageCode: 'ja',
        locationRestriction: {
          circle: {
            center: { latitude: lat, longitude: lng },
            radius: 500.0,
          },
        },
      }),
    });
 
    const data = await response.json();
 
    if (!response.ok) {
      return NextResponse.json(data, { status: response.status });
    }
    return NextResponse.json(data, { status: 200 });
  } catch (error) {
    console.error(error);
    return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
  }
}
 

400番エラーになる

ログ出力してみるとこう書いてある。
言語コード「*」が無効です。https://developers.google.com/maps/faq#languagesupport のサポート言語リストを参照してください"

{
  error: {
    code: 400,
    message: "Invalid language code '*'. See the list of supported languages at https://developers.google.com/maps/faq#languagesupport",
    status: 'INVALID_ARGUMENT'
  }
}

公式ドキュメントを見る

image.png

🤔「いや、省略してもいいって書いてあるやん」

コードを修正する

API作成時のbodyに言語コードを設定したところ、正しく取得できました。

  body: JSON.stringify({
    includedTypes: ['restaurant'],
    maxResultCount: 10,
    languageCode: 'ja',
    locationRestriction: {
      circle: {
        center: { latitude: lat, longitude: lng },
        radius: 500.0,
      },
    },
  }),

...

関連記事

agents-browserPlaywrightAI

AIエージェント向けに最適化されてたagents-browserをPlaywright MCPと比較検証してみた

agents-browserの「Up to 93% less context than Playwright MCP」は本当か気になったので、Yahoo! JAPANを対象にPlaywright MCPと比較してデータ削減率とトークン消費量を検証します。

記事を読む
Playwright

やはり俺のPlaywrightはまちがっている。

過去のプロジェクトから流用したPlaywrightのコードは「動いて」いました。しかし、偶然ドキュメントを読み直したとき、「動く」と「正しく動く」の間には設計思想の違いがあることに気づきました。page.evaluate()ではなくlocatorを使うべき理由、waitForNavigation()が非推奨である理由。公式ドキュメントには、単なるAPIリファレンスではなく「なぜこの方法が推奨されるのか」が書かれています。時間がない現実の中で、それでもドキュメントを読む価値とは何かを考えます。

記事を読む
ブログAI

図解から始める認知負荷との付き合い方

AI時代、文字を読む量が圧倒的に増えています。生成AIからの提案を承認する度に大量のテキストを読み込む認知負荷の高さに「もう無理だ」と感じた経験から、技術ブログに図解機能を実装しました。図解は「記憶の定着装置」として機能し、全体像を視覚的に示すことで認知負荷を下げます。本記事では、なぜ図解が有効なのか、そしてAIを活用してどう実装したのかを解説します。

記事を読む