質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

92.00%

  • Java

    8362questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Ajax

    658questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • JSON

    553questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

  • Spring

    344questions

    Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Spring4:ResponseBodyで返した日本語が文字化けする

受付中

回答 1

投稿 2016/04/14 17:15 ・編集 2016/04/15 17:46

  • 評価
  • クリップ 1
  • VIEW 1,826

Zaganchan

score 4

発生している問題・エラーメッセージ

Ajax通信でSpringから返した値のうち、日本語が全て半角の「?」に置き換わってしまいます。
?は文字数に対応しているため、マルチバイトのみ全て?になっていると思われます。

該当のソースコード

Spring

@RequestMapping(value = "/test", method = RequestMethod.POST, headers = {"Content-type=application/json;charset=UTF-8,application/xml;charset=UTF-8,text/plain;charset=UTF-8"},consumes = {"application/json; charset=UTF-8,text/plain;charset=UTF-8"})
    @ResponseBody
    public String child_kensaku(@RequestBody String inputdata , HttpServletRequest request, HttpServletResponse response, HttpSession session, SessionStatus sessionstatus
            ) throws IllegalArgumentException, IllegalAccessException, ParseException, JsonProcessingException{
        ObjectMapper mapper = new ObjectMapper();
        String ret = mapper.writeValueAsString(jsonstr); //jsonstrに日本語のデータがある

        return ret;
    }


JS

$(function(){
    $("#ajax_btn").click(function ajaxpost() {
        // 多重送信を防ぐため通信完了までボタンをdisableにする
        var button = $(this);
        button.attr("disabled", true);

        // 各フィールドから値を取得してJSONデータを作成
        var data = {
            'testdata': 'testdata',
            beforeSend: function(xhr) {
                 xhr.overrideMimeType('application/json; charset=UTF-8');
            }
        };
        return $.ajax({
            type:"POST",                // method = "POST"
            url:"test.html",        // POST送信先のURL,
            data:JSON.stringify(data),  // JSONデータ本体
            contentType: 'application/json; charset=UTF-8', // リクエストの Content-Type
            dataType: "json",           // レスポンスをJSONとしてパースする
        })

        .done(function(result) {
            console.log(result);
        }).fail(function() {
            // エラー
            alert("通信エラー。リトライしてください。");
        }).always(function(result) {
            // 完了処理
        });
    });
});

Maven

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.7.3</version>
        </dependency>


Config

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes" value="text/plain;charset=UTF-8,application/json;charset=UTF-8,application/xml;charset=UTF-8,text/plain;charset=UTF-8" />
            <property name="writeAcceptCharset" value="false" />
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

試したこと

Produces="application/json; charset=UTF-8"
を@RequestMappingに追加すればよいという情報は見つけられたのですが、それをするとJSから呼び出した際にMappingがうまくいかず、メソッドが呼び出せません。
そのためheadersに"Content-type=application/json;charset=UTF-8"を指定しています。(これで代用がきくかと考えていたのですがきかないのでしょうか・・・)
headersやconsumesについては手当たり次第つけてみたのですが効果は現れませんでした…

また、Web.xmlにはEncoding Filterを、Spring Securityより上に定義済みです。

補足

Java8 Spring4.2 Tomcat8

暫定対応

JsonをJava上で一度Unicodeにescapeし、JSで受け取ってからunescapeすることで何とか通信しています・・・が・・・遅い・・・

  • 気になる質問をクリップする

    クリップした質問に回答があった場合に通知・メールを受け取ることができます。

    クリップした質問はマイページの「クリップ」タブからいつでも見ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

@RequestMappingproduces="application/json;charset=UTF-8"に設定を追加れば文字化けしなくなるかと。

@RequestMapping(value = "/test", method = RequestMethod.POST, produces="application/json;charset=UTF-8)
@ResponseBody
public String child_kensaku(@RequestBody String inputdata , HttpServletRequest request, HttpServletResponse response, HttpSession session, SessionStatus sessionstatus
        ) throws IllegalArgumentException, IllegalAccessException, ParseException, JsonProcessingException{
    ObjectMapper mapper = new ObjectMapper();
    String ret = mapper.writeValueAsString(jsonstr); //jsonstrに日本語のデータがある

    return ret;
}

検証してみましが、Mappingがうまくいかず、メソッドが呼び出せません。 という状況が再現できませんでした。
再現に使用したソースは以下の通りとなります

JDK8 u77
Eclipse 4.5 mars2
Tomcat 8.0.33 with log4j1.2
spring-webmvc 4.2.5.RELEASE

TestController.java

package sandbox.slp.mvc;

import java.text.ParseException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.SessionStatus;

import com.fasterxml.jackson.core.JsonProcessingException;

@Controller
public class TestController {

    private static final Logger log = LoggerFactory.getLogger(TestController.class);

    @RequestMapping(value = "/test/1", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String child_kensaku(@RequestBody String inputdata, HttpServletRequest request, HttpServletResponse response,
            HttpSession session, SessionStatus sessionstatus)
                    throws IllegalArgumentException, IllegalAccessException, ParseException, JsonProcessingException {
        log.info(inputdata);
        return "{ \"name\":\"日本語\"}";
    }
}


index.html

<!DOCTYPE html>
<html>
<head>
<title>jQuery ajax POST sample</title>
<script
    src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script>
    $(function() {
        $("#ajax_btn").click(function ajaxpost() {
            var formData = {
                name : "日本語文字列入お名前",
                age : "31"
            }; 

            $.ajax({
                url : "test/1/",
                type : "POST",
                data : JSON.stringify(formData),
                contentType : 'application/json;charset=UTF-8', // リクエストの Content-Type
                dataType : "json", // レスポンスをJSONとしてパースする
                success : function(data, textStatus, jqXHR) {
                    //data - response from server
                    console.log(data);
                },
                error : function(jqXHR, textStatus, errorThrown) {

                }
            });
        });
    });
</script>
</head>

<body>
    <input id="ajax_btn" type="button" value="1押す" />
</body>
</html>


servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  <mvc:annotation-driven />
  <mvc:resources
    mapping="/resources/**"
    location="/resources/" />
  <mvc:resources
    mapping="/*"
    location="/" />
</beans:beans>


pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>sandbox</groupId>
  <artifactId>sandbox.slp</artifactId>
  <name>sandbox.slp</name>
  <packaging>war</packaging>
  <version>1.0.0-BUILD-SNAPSHOT</version>
  <properties>
    <org.springframework-version>4.2.5.RELEASE</org.springframework-version>
  </properties>
  <dependencies>
    <!-- Spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${org.springframework-version}</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.7</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.7.3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.7.3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.7.3</version>
    </dependency>
  </dependencies>
</project>


サーバ側でのログ出力

17:52:49.271 [http-nio-8080-exec-25] INFO  sandbox.slp.mvc.TestController - {"name":"日本語文字列入お名前","age":"31"}

クライアント側でのログ出力

Object {name: "日本語"}


また、以下の依存関係を追加し、オブジェクトのままjsonstrを返却すれば@RequestMapping(value = "/test")のみで文字化けせずにJSONデータとして返却されるようになります。

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.7.3</version>
</dependency>

投稿 2016/04/16 03:08

編集 2016/04/16 18:04

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/04/18 10:57 編集

    検証までして頂いてありがとうございます。
    Mappingのエラーは再現しないのですね・・・
    環境の伝え漏れがあるのかもしれません。申し訳ないです。

    umed0025さんが検証されたことと同様のことを私の環境で実行しますと、
    サーバ側でのログ出力 →日本語で正常に表記される。
    クライアント側でのログ出力 →日本語は?に置換される。

    jackson-databindを導入してjsonstrをそのまま返す
    →Jsonデータは作成されているが、日本語部分が全て?に置換されている。

    という状況です。

    関係あるかは分からないのですが、ThymeleafでHTMLを呼び出しています。それに当たってJSPの優先度を下げています。

    servlet-context.xml
    ```
    <!-- Thymeleaf -->
    <!-- <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" /> -->

    <bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
    <property name="prefix" value="/WEB-INF/views" />
    <property name="suffix" value=".html" />
    <property name="templateMode" value="HTML5" />
    <property name="characterEncoding" value="UTF-8" />
    </bean>

    <bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
    <property name="templateEngine">
    <bean class="org.thymeleaf.spring4.SpringTemplateEngine">
    <property name="templateResolver" ref="templateResolver" />
    </bean>
    </property>
    <property name="order" value="2" />
    <property name="characterEncoding" value="UTF-8" />
    </bean>

    <!-- JSP -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
    <property name="order" value="3" />
    </bean>
    ```

    jsonstrをそのまま返しても?に置換されるということは文字コードの問題ではなくて何か別の問題(サーブレットの設定等・・?)なのでしょうか…

    また、producesについてはリクエストヘッダのAccept部分、headerについてはリクエストヘッダを全て見るということで認識しているのですが、headerで指定していればProduceで指定するのと同等の効果が得られるということではないのでしょうか?

    要領を得ない質問で申し訳ございませんが、どうかまたお返事いただければ幸いです。

    キャンセル

  • 2016/04/22 16:59

    「https://github.com/umed0025/ssmjs」にシンプルな構成で確認するプロジェクトを作成しました。
    もしこの環境で日本語が???になってしまうようであれば、Springの設定外(OSやTomcatなど)でしょうか。
    正常に日本語の文字列が帰るようであれば、web.xmlまたはsrpingの設定ファイルまわりが怪しいです。1づづ設定を追加して確認してみるのはどうでしょう?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

92.00%

関連した質問

同じタグがついた質問を見る

  • Java

    8362questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Ajax

    658questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • JSON

    553questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

  • Spring

    344questions

    Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

閲覧数の多いJavaの質問