Help us understand the problem. What is going on with this article?

VisualForce で rerender すると4バイト文字が化ける

問題点

SalesForce の VisualForce で rerender すると
4バイト文字が文字化けする

サンプル

単純にボタン押したら再描画するだけの画面を作成

Test.vfp
<apex:page standardController="User" extensions="TestController" title="Test">
    <div>rerender範囲外:𠮷野家</div>
    <apex:form id="frm">
        <div>rerender範囲内:𠮷野家</div>
        <apex:commandButton value="rerender" action="{!act}" status="reloadStatus" rerender="frm" />
    </apex:form>
</apex:page>

TestController.apxc
public class TestController {
    public TestController(ApexPages.StandardController controller) {

    }

    public void act(){
        return;
    }
}

これで rerender ボタンを押下すると

before.png
 ↓
after.png

rerender 範囲内の「𠮷野家」が「ஷ野家」になってしまう
※範囲外に関しては変更なし

調査

文字コード

とりあえず「𠮷」と「」のコードポイント調べた

Test.js
console.log(''.codePointAt().toString(16));    // 0x0bb7
console.log('𠮷'.codePointAt().toString(16));    // 0x20bb7

絶対これや
サロゲートペア文字(4バイト文字)がおかしくなる模様

欠損箇所

rerender の範囲外は正常なことから apex:commandButton が怪しい
ボタン押下時は Ajax で Apex にアクセスしてるようなのでレスポンス内容を見てみる

Response
<?xml version="1.0"?>
<html lang="en_US" xmlns="http://www.w3.org/1999/xhtml"><head>
    <!--省略-->
</head>
<body>
    <form id="j_id0:frm" name="j_id0:frm" method="post" action="https://hogehoge.visual.force.com/apex/Test?core.apexpages.request.devconsole=1" enctype="application/x-www-form-urlencoded">
        <input type="hidden" name="j_id0:frm" value="j_id0:frm" /> 
        <div>rerender範囲内:ஷ野家</div>
    <!--省略-->
</body>
</html>

もう化けとる
このへん見る限り XML ではサロゲートペア使えないっぽい

数値文字参照 &#x20bb7; にすればいけるかな~と思ったけど
状況変わらず Ajax のレスポンス時点で文字化けしてた。

対策

苦肉の策としてエスケープを挟むことにした
画面側でデコードできればURLエンコードとか他のでもいいと思う

Test.vfp
<apex:page standardController="User" extensions="TestController" title="Test">
    <div>rerender範囲外:𠮷野家</div>
    <apex:form id="frm">
        <div id="yoshi" style="visibility:hidden;">%uD842%uDFB7</div>
        <apex:commandButton value="rerender" action="{!act}" status="reloadStatus" rerender="frm" />
        <script>
            var ysdiv = document.getElementById('yoshi')
            ysdiv.innerHTML = unescape(ysdiv.innerHTML);
            ysdiv.style.visibility = "visible";
        </script>
    </apex:form>
</apex:page>

エスケープ後の文字列を表示してJSで無理矢理元に戻す感じ
<script>rerender 内に置かないと動かないので注意

もうちょいきれいな対策したい

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした