Anda ingin membuat serialisasi model Anda sebagai array objek yang berisi nama properti dan nilai properti, yang nama dan nilainya berasal dari serialisasi JSON default untuk model Anda. Anda dapat melakukannya dengan generik khusus JsonConverter<T>
yang menerjemahkan antara default serialisasi dan serialisasi array.
Secara default, model UserPtr
Anda harus diserialkan sebagai berikut:
{
"my_var1": 1,
"my_var2": 2,
"my_var3": 2,
"my_var4": 4
}
Namun sebaliknya, Anda menerima array objek yang berisi pasangan nama/nilai tunggal seperti yang ditunjukkan dalam pertanyaan Anda, yang namanya sesuai dengan nama properti model Anda. Anda ingin mengikat array ini ke model Anda. Untuk mencapai hal ini, Anda dapat membuat konverter generik yang serupa dengan yang ada dari Deserialisasi JSON dari hasil pencarian Sharepoint 2013 ke dalam daftar Kelas Saya sebagai berikut:
public class NamePtrPropertyArrayConverter<T> : JsonConverter<T> where T : class, new()
{
struct NamePtrDTO
{
public string name;
public object ptr;
}
public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
{
var obj = (JObject)JsonExtensions.DefaultFromObject(serializer, value);
serializer.Serialize(writer, obj.Properties().Select(p => new NamePtrDTO { name = p.Name, ptr = p.Value }));
}
public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
return null;
var array = serializer.Deserialize<List<NamePtrDTO>>(reader);
var obj = new JObject(array.Select(i => new JProperty(i.name, i.ptr)));
existingValue = existingValue ?? (T)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
using (var subReader = obj.CreateReader())
serializer.Populate(subReader, existingValue);
return existingValue;
}
}
public static partial class JsonExtensions
{
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None) // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
// DefaultFromObject() taken from this answer https://stackoverflow.com/a/29720068/3744182
// By https://stackoverflow.com/users/3744182/dbc
// To https://stackoverflow.com/questions/29719509/json-net-throws-stackoverflowexception-when-using-jsonconvert
public static JToken DefaultFromObject(this JsonSerializer serializer, object value)
{
if (value == null)
return JValue.CreateNull();
var dto = Activator.CreateInstance(typeof(DefaultSerializationDTO<>).MakeGenericType(value.GetType()), value);
var root = JObject.FromObject(dto, serializer);
return root["Value"].RemoveFromLowestPossibleParent() ?? JValue.CreateNull();
}
public static JToken RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
return null;
// If the parent is a JProperty, remove that instead of the token itself.
var contained = node.Parent is JProperty ? node.Parent : node;
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (contained is JProperty)
((JProperty)node.Parent).Value = null;
return node;
}
interface IHasValue
{
object GetValue();
}
[JsonObject(NamingStrategyType = typeof(DefaultNamingStrategy), IsReference = false)]
class DefaultSerializationDTO<T> : IHasValue
{
public DefaultSerializationDTO(T value) => this.Value = value;
public DefaultSerializationDTO() { }
[JsonConverter(typeof(NoConverter)), JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Serialize)]
public T Value { get; set; }
object IHasValue.GetValue() => Value;
}
}
public class NoConverter : JsonConverter
{
// NoConverter taken from this answer https://stackoverflow.com/a/39739105/3744182
// By https://stackoverflow.com/users/3744182/dbc
// To https://stackoverflow.com/questions/39738714/selectively-use-default-json-converter
public override bool CanConvert(Type objectType) { throw new NotImplementedException(); /* This converter should only be applied via attributes */ }
public override bool CanRead => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => throw new NotImplementedException();
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
}
Kemudian, lakukan deserialisasi dengan menambahkan konverter ke JsonSerializerSettings.Converters
:
var settings = new JsonSerializerSettings
{
Converters = { new NamePtrPropertyArrayConverter<UserPtr>() },
};
var model = JsonConvert.DeserializeObject<UserPtr>(strJson, settings);
Atau terapkan konverter langsung ke model Anda sebagai berikut:
[JsonConverter(typeof(NamePtrPropertyArrayConverter<UserPtr>))]
public class UserPtr
{
// Contents unchanged
}
Demo biola di sini.
person
dbc
schedule
03.03.2021
"Value_my_var1"
menjadi bilangan bulat. Bolehkah saya berasumsi bahwa ini sebenarnya adalah nilai integer yang Anda ganti saat mengetik pertanyaan Anda? - person dbc   schedule 04.03.2021ptr
sebenarnya dari objekmy_varX
semuanya adalah bilangan bulat yang valid, dan mengedit pertanyaan Anda untuk mencerminkan hal itu. Jika hasil edit saya salah, harap edit ulang pertanyaan Anda untuk menyertakan contoh minimal yang dapat direproduksi. - person dbc   schedule 04.03.2021