Serialize subset of class

Refresh

December 2018

Views

383 time

4

I won't go into all the things I've tried...

This is approximately what I'm trying to accomplish.

public interface IClientDTO {
    string FirstName { get; }
    string LastName { get; }
}

public class DTO : IClientDTO {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string SSN { get; set; }
}

class Program {
    static void Main(string[] args) {
        DTO dto = new DTO() { FirstName = "John", LastName = "Doe", SSN = "111001111" };
        IClientDTO clientDTO = dto;
        string sDTO = JsonConvert.SerializeObject(dto);
        string sClientDTO = JsonConvert.SerializeObject(clientDTO);

        Debug.WriteLine(sDTO);
        Debug.WriteLine(sClientDTO);
    }
}

I would like my output to look like this...

{"SSN":"111001111","FirstName":"John","LastName":"Doe"}

{"FirstName":"John","LastName":"Doe"}

I didn't think it would be that difficult, but since the Serializer always determines the type as DTO I always get the SSN value even on the occasions I don't want to.

This is of course just a little test. Lets say that I have a WebAPI application mocked up something like this.

public class AdminController : ApiController {
    public DTO Get() { return new Model().DTO); }
}

public class ClientController : ApiController {
    public IClientDTO Get() { return new Model().DTO); }
}

I'd like the Serializer to serialize only those items defined in the return type.

3 answers

1

Мне нравится контроль доступ к объектам через вернувшиеся интерфейсы. Его приятно, что компилятор контролирует доступ и видимость.

Однако, когда речь идет о сериализации компилятор не там судьи. Так что я думаю, что мой вопрос является спорным один. Как только вопросы, Serializer Json.NET ...

return base.Serializer._contractResolver.ResolveContract(value.GetType());

Это в значительной степени дело сделано. Конечно, вы можете домкрат с вещами и тыкать вещи, но если вы не можете сделать это в глобальном масштабе на основе типа я не вижу смысл. Так что я собираюсь что-то вроде этого на основе предложения Кэма.

public interface IClientDTO {
    string FirstName { get; }
    string LastName { get; }
}

public interface IAdminDTO {
    string FirstName { get; }
    string LastName { get; }
    string SSN { get; }
}

class ClientDTO : IClientDTO {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class AdminDTO : IAdminDTO {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string SSN { get; set; }
}

class Model {
    class DTO {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string SSN { get; set; }
    }
    private DTO dto = new DTO() { FirstName = "John", LastName = "Doe", SSN = "111001111" };
    public IClientDTO ClientDTO { get { return new ClientDTO() { FirstName = dto.FirstName, LastName = dto.LastName }; } }
    public IAdminDTO AdminDTO { get { return new AdminDTO() { SSN = dto.SSN, FirstName = dto.FirstName, LastName = dto.LastName }; } }
}

class Program {

    static void Main(string[] args) {

        Model model = new Model();
        string sClientDTO = JsonConvert.SerializeObject(model.ClientDTO);
        string sAdminDTO = JsonConvert.SerializeObject(model.AdminDTO);

        Debug.WriteLine(sClientDTO);
        Debug.WriteLine(sAdminDTO);

    }
}

Конечно, это немного неуклюжее и повторяющиеся, но она по-прежнему позволяет мне поддерживать доступ через интерфейсы, и я могу позволить сериализатору делать свое дело беспрепятственным, и я подозреваю, что это будет легче поддерживать в долгосрочной перспективе.

0

Вы можете использовать ContractResolver справиться с этим:

private class IgnoreSSNResolver : DefaultContractResolver
{

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        Debug.Write(type.Name);
        var properties = base.CreateProperties(type, memberSerialization);

        var props = properties.Where((x) => x.PropertyName != "SSN");


        return props.ToList();
    }
}

Затем, когда вы сериализации, вы просто делаете это:

JsonSerializerSettings sets = new JsonSerializerSettings();
sets.ContractResolver = new IgnoreSSNResolver();

string sClientDTO = JsonConvert.SerializeObject (clientDTO,sets);
1

Вы можете использовать , JsonIgnoreAttributeчтобы всегда не включают в себя номер социального страхования.

public class DTO : IClientDTO {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    [JsonIgnore]
    public string SSN { get; set; }
}

Если вы хотите , чтобы определить погоду программно включать или не включать его, вы можете создать два класса - базы ClientDTOс FirstName, LastName и т.д. Тогда А ClientWithSSNтипа, который наследует от ClientDTOи содержит только номер социального страхования. Затем, когда они выбрали , чтобы вернуть SSN или нет, приведение к базовому типу, без ССН или вернуть фактический ClientWithSSNтип.