#c# #json #json.net #deserialization
#c# #json #json.net #десериализация
Вопрос:
У меня есть класс с именем Arg
. Свойство ArgValue
имеет тип System.Object
.
public class Arg
{
public string ArgName { get; set; }
public object ArgValue { get; set; }
}
Если я хочу десериализовать JSON-строку следующим образом:
string json = @"{""ArgName"":""arg"",""ArgValue"":""/something/more/than/a/string/""}";
var jsonSerializerSettings = new JsonSerializerSettings() { };
Arg arg = JsonConvert.DeserializeObject<Arg>(json, jsonSerializerSettings);
Я получаю объект Arg с его значениями следующим образом:
ArgName
имеет типstring
->arg
ArgValue
имеет типobject {string}
->/something/more/than/a/string/
Я этого не хочу JSON.NET преобразует его в System.String
. Если свойство имеет тип System.Object
, оно не должно преобразовывать его в строку.
Было бы лучше, если бы он оставил его нетронутым, и значение было бы типа: JToken (или JValue).
Существует ли опция JsonSerializerSettings для настройки такого поведения?
Дополнительная информация:
Строковое значение в свойстве ArgValue
«больше, чем строка», и мне нужно преобразовать его позже самостоятельно. JsonConverter
здесь не может быть использовано, потому что я не знаю конкретный тип объекта на данный момент. позже я знаю и должен использовать JToken.ToObject<MySpecialType>()
. (После чего он будет правильно преобразован a JsonConverter
).
Комментарии:
1. ну, преобразование между string и object означает отправку распаковки, но в вашем случае json содержит строки, а не объекты, поэтому он уже выполняет то, что вы хотите получить.
2. Ну, это потому, что нет необходимости разбирать строковое значение — строка также является объектом. Если вам нужен конкретный тип, укажите его, если вы не знаете тип, используйте generics .
3. Пожалуйста, укажите, почему вы хотите такого поведения?
4. Строковое значение в свойстве «ArgValue» — «больше, чем строка», и мне нужно преобразовать его позже самостоятельно. JsonConverter здесь не может быть использован, потому что я не знаю конкретный тип объекта на данный момент. позже я знаю, и мне нужно использовать JToken. ToObject<MySpecialType>() . (После чего он будет правильно преобразован с помощью JsonConverter).
Ответ №1:
Как я уже указывал в комментарии, строка json, которую вы хотите десериализовать, будет десериализована в объект класса с двумя свойствами, оба типа string . Это связано с тем, что при указании "ArgName" : "arg"
двух кавычек между arg
метками указывается значение типа string . Это также случай ArgValue
, который сериализуется также как строка.
Выполнив эту строку кода:
Arg arg = JsonConvert.DeserializeObject<Arg>(json, jsonSerializerSettings);
Вы получаете object ( arg
) типа Arg
, который точно соответствует классическому объекту типа Arg
. Это эквивалентно выполнению:
Arg arg = new Arg{ ArgName = "arg", ArgValue = "/something/more/than/a/string/" };
Строковое присвоение свойства ArgValue
, которое ожидает объект, является тем же самым в случае десериализации, это не преобразование (или, лучше сказать, приведение), это только бокс.
Комментарии:
1. @user437899 извините, как это создается, как с object property ?
2. извините, я нажал «ввод», и комментарий был добавлен до того, как я закончил 🙂
3. На стороне клиента класс создается следующим образом: Arg arg = new Arg{ ArgName = «arg», ArgValue = new QualifiedName(«/something/more/than/a/string/») }; значение имеет тип «namespace.Qualifiedname». На стороне сервера он должен быть того же типа, после всех этапов конвейера. Сначала выполняется синтаксический анализ, а затем он должен использовать реализацию JsonConverter для изменения типа. Но я не знаю тип свойства «ArgValue» во время десериализации / синтаксического анализа.
4. @user437899 Я предлагаю вам сохранить его таким
object
, каким вы его сделали, потому что, если вы не знаете его тип в тот момент, когда вы десериализуете это свойство, то сохранение в качестве объекта, а затем приведение его после — это единственное, что вы можете сделать. Вы можете попробовать десериализовать какdynamic
тип, но это будет менее безопасно.5. Хорошо, спасибо. единственный способ, который я вижу, — это самостоятельно десериализовать объект на «более низком уровне», а затем я могу решить, как десериализовать свойство. (Оно должно быть типа JToken)
Ответ №2:
Для последующего преобразования вы можете использовать
Общие
public class Arg<T>
{
public string ArgName { get; set; }
public T ArgValue { get; set; }
}
затем вы можете передать целевой тип следующим образом:
JsonConvert.DeserializeObject<Arg<Qualifiedname>>(somestring);
или
public Arg<T> Deserialize<T>(string somestring){
return JsonConvert.DeserializeObject<Arg<T>>(somestring);
}
Оставьте его как JToken
public class Arg
{
public string ArgName { get; set; }
public JToken ArgValue { get; set; }
}
Десериализуйте его позже с помощью JsonConvert
public class Arg
{
public string ArgName { get; set; }
public string ArgValue { get; set; }
}
или просто передавайте его целиком как строку, пока не узнаете, какой тип будет проанализирован..
Комментарии:
1. Я не могу сделать свойство JToken, потому что класс «Arg» является классом DTO, который также используется другими форматами передачи.
2. Не могли бы вы использовать Generics или более позднюю десериализацию?