【问题标题】:"Unable to translate Unicode character \\uD83C" error when returning JSON from asp.net POST method从 asp.net POST 方法返回 JSON 时出现“无法翻译 Unicode 字符 \\uD83C”错误
【发布时间】:2016-11-12 17:51:50
【问题描述】:

我在 MVC 项目中开发了一个 web api。我在我的 post 方法中返回一个 JToken 对象。通常我的 api 可以正常工作,但有时在特定数据中我会收到此错误:

  "Message": "An error has occurred.",
  "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
  "ExceptionType": "System.InvalidOperationException",
  "StackTrace": null,
  "InnerException": {
  "Message": "An error has occurred.",
  "ExceptionMessage": "Unable to translate Unicode character \\uD83C 
   at index 411 to specified code page."

这是我的发帖方式

public JToken Post([FromBody]Classes.Search search)
    {

        Classes.ReturnSearch returnSearch = new Classes.ReturnSearch();
        try
        {
            string con = System.Configuration.ConfigurationManager.ConnectionStrings["TConnectionString"].ConnectionString;
            SqlConnection cn = new SqlConnection(con);
            SqlDataAdapter sqlDataAdapter = new SqlDataAdapter("SP_Searchi", cn);
            sqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
            sqlDataAdapter.SelectCommand.Parameters.Add(new SqlParameter("@word", search.word));

            sqlDataAdapter.SelectCommand.Parameters.Add(new SqlParameter("@num", search.num));
            DataSet d = new DataSet();
            sqlDataAdapter.Fill(d);
            DataTable table = d.Tables[0];

            foreach(DataRow row in table.Rows)
            {
                string result=row[1].ToString();

                returnSearch.search_items.Add(new Classes.SearchItem(row[0].ToString(), row[1].ToString(),search.word));
            }
            returnSearch.status = "Success";


            return JObject.Parse(JsonConvert.SerializeObject(returnSearch));
        }
        catch (Exception e)
        {
            returnSearch.status = "Failed";
            returnSearch.search_items = null;
            ValuesController.Log("Error in Search: "+e.Message);
            return JObject.Parse(JsonConvert.SerializeObject(returnSearch));
        }


    }

有什么问题?!

【问题讨论】:

  • U+D83C is not a valid unicode character。这个角色最初是如何出现在您返回的对象中的?
  • 我继续修改了您的原始标题旋转后重叠回收视图,以更能反映问题。如果不受欢迎,请随时改回来。

标签: c# asp.net-mvc post unicode json.net


【解决方案1】:

这是一个表情符号修饰符。您可能会在解析输入的表情符号后看到它(可以拆分为多个 \u#### 实例)。

【讨论】:

    【解决方案2】:

    您的问题是 U+D83C is not a valid unicode character 以某种方式进入了您的 returnSearch 对象内的字符串之一。随后,asp.net-mvc 框架抛出异常,试图将这样的字符编码为 utf-8。

    您需要做的是确定此角色如何进入您的returnSearch 结果并解决该潜在问题。由于您已经手动将返回的结果转换为JObject,为了使调试更容易,您可以使用以下转换器将所有字符串测试编码为 utf-8 并在出现问题时抛出异常:

    public class EncodingValidatingStringConverter : JsonConverter
    {
        readonly Encoding encoding;
    
        public EncodingValidatingStringConverter()
            : this(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderReplacementFallback("?"), new DecoderExceptionFallback()))
        {
        }
    
        public EncodingValidatingStringConverter(Encoding encoding)
        {
            if (encoding == null)
                throw new ArgumentNullException();
            this.encoding = encoding;
        }
    
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(string);
        }
    
        public override bool CanRead { get { return false; } }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var s = (string)value;
            var bytes = encoding.GetBytes(s);
            var sFixed = encoding.GetString(bytes);
    
            writer.WriteValue(sFixed);
        }
    }
    

    然后修改您的Post() 方法以捕获并记录EncoderFallbackException 并按照似乎可取的方式处理问题。例如,以下版本的方法在记录后将无效字符替换为 ? 字符:

            try
            {
                // Fill in the returnSearch
    
                // Convert to JObject and return
                var settings = new JsonSerializerSettings
                {
                    Converters = new[] { new EncodingValidatingStringConverter(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderExceptionFallback(), new DecoderExceptionFallback())) },
                };
                return JObject.FromObject(returnSearch, JsonSerializer.CreateDefault(settings));
            }
            catch (EncoderFallbackException ex)
            {
                // Log the encoding error for debugging:
                ValuesController.Log("Encoding exception:\n" + ex.ToString());
                // You could log the search parameters or entire search_items list as well if desired.
    
                // Return whatever seems most advisable, e.g. replacing the bad character with a fallback if preferred.
                var settings = new JsonSerializerSettings
                {
                    Converters = new[] { new EncodingValidatingStringConverter(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderReplacementFallback("?"), new DecoderExceptionFallback())) },
                };
                return JObject.FromObject(returnSearch, JsonSerializer.CreateDefault(settings));
            }
            catch (Exception ex)
            {
                returnSearch.status = "Failed";
                returnSearch.search_items = null;
                ValuesController.Log("Error in Search: " + ex.Message);
                var settings = new JsonSerializerSettings
                {
                    Converters = new[] { new EncodingValidatingStringConverter(Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderReplacementFallback("?"), new DecoderExceptionFallback())) },
                };
                return JObject.FromObject(returnSearch, JsonSerializer.CreateDefault(settings));
            }
    

    请注意,对每个字符串进行测试编码会对性能产生负面影响,因此一旦您解决了根本问题,您应该删除此解决方法。

    顺便说一句,您可以使用JObject.FromObject(returnSearch) 而不是JObject.Parse(JsonConvert.SerializeObject(returnSearch))。此方法直接写入JToken 层次结构,无需中间字符串表示,因此应该具有更好的性能。

    【讨论】:

      猜你喜欢
      • 2015-01-13
      • 1970-01-01
      • 2015-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多