Отмеченный ответ не выполнен на 100%, так как он игнорирует любой IContractResolver, который может быть зарегистрирован, например CamelCasePropertyNamesContractResolver и т. д.
Также возврат false для can convert может предотвратить другие случаи пользователя, поэтому я изменил его на return objectType.GetCustomAttributes(true).OfType
Вот обновленная версия: https://dotnetfiddle.net/F8C8U8
Я также удалил необходимость установить JsonProperty
на свойство, как показано в ссылке.
Если по какой-либо причине ссылка выше умирает или взрывается, я также включаю следующий код:
public class JsonPathConverter : JsonConverter
{
///
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
object targetObj = Activator.CreateInstance(objectType);
foreach (PropertyInfo prop in objectType.GetProperties().Where(p => p.CanRead && p.CanWrite))
{
JsonPropertyAttribute att = prop.GetCustomAttributes(true)
.OfType()
.FirstOrDefault();
string jsonPath = att != null ? att.PropertyName : prop.Name;
if (serializer.ContractResolver is DefaultContractResolver)
{
var resolver = (DefaultContractResolver)serializer.ContractResolver;
jsonPath = resolver.GetResolvedPropertyName(jsonPath);
}
if (!Regex.IsMatch(jsonPath, @"^[a-zA-Z0-9_.-]+$"))
{
throw new InvalidOperationException($"JProperties of JsonPathConverter can have only letters, numbers, underscores, hiffens and dots but name was ${jsonPath}."); // Array operations not permitted
}
JToken token = jo.SelectToken(jsonPath);
if (token != null && token.Type != JTokenType.Null)
{
object value = token.ToObject(prop.PropertyType, serializer);
prop.SetValue(targetObj, value, null);
}
}
return targetObj;
}
///
public override bool CanConvert(Type objectType)
{
// CanConvert is not called when [JsonConverter] attribute is used
return objectType.GetCustomAttributes(true).OfType().Any();
}
///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var properties = value.GetType().GetRuntimeProperties().Where(p => p.CanRead && p.CanWrite);
JObject main = new JObject();
foreach (PropertyInfo prop in properties)
{
JsonPropertyAttribute att = prop.GetCustomAttributes(true)
.OfType()
.FirstOrDefault();
string jsonPath = att != null ? att.PropertyName : prop.Name;
if (serializer.ContractResolver is DefaultContractResolver)
{
var resolver = (DefaultContractResolver)serializer.ContractResolver;
jsonPath = resolver.GetResolvedPropertyName(jsonPath);
}
var nesting = jsonPath.Split('.');
JObject lastLevel = main;
for (int i = 0; i < nesting.Length; i++)
{
if (i == nesting.Length - 1)
{
lastLevel[nesting[i]] = new JValue(prop.GetValue(value));
}
else
{
if (lastLevel[nesting[i]] == null)
{
lastLevel[nesting[i]] = new JObject();
}
lastLevel = (JObject)lastLevel[nesting[i]];
}
}
}
serializer.Serialize(writer, main);
}
}
Вам просто нужно динамически выделить его (потому что он, вероятно, должен пережить объем, в котором вы его используете), а затем преобразовать его туда и обратно:
// Cast a dynamically allocated string to 'void*'.
void *vp = static_cast<void*>(new std::string("it's easy to break stuff like this!"));
// Then, in the function that's using the UserEvent:
// Cast it back to a string pointer.
std::string *sp = static_cast<std::string*>(vp);
// You could use 'sp' directly, or this, which does a copy.
std::string s = *sp;
// Don't forget to destroy the memory that you've allocated.
delete sp;
На основании вашего комментария «Я имел в виду преобразовать то, на что указывает пустота * (которая является строкой), в строку».
Предполагая, что у вас есть это:
std::string str = ...;
void *ptr = &str;
Вы можете просто привести обратно к строке:
std::string *pstr = static_cast<std::string *>(ptr);
Заметьте, что вы должны убедиться, что ptr
действительно указывает на std::string
. Если вы ошибаетесь и это указывает на что-то еще, это приведет к неопределенному поведению.
Если void является const char *, то вы можете просто вызвать с ним конструктор std :: string, т.е.
const char* cakes = something;
std::string lols = std::string(cakes);
Если вы пытаетесь отформатировать адрес как текст, вы можете использовать строковый поток
:
std::stringstream strm;
strm << ptr;
std::string str = strm.str();
// str will now have something like "0x80004567"
Если это не то, что вас интересует, уточните свой вопрос.