diff --git a/internal/gnmiserver/model.go b/internal/gnmiserver/model.go
index 98301308ceac44203aa4419653572c79b3920b74..60de0aeb83325f747358d5ab93d6fcbc269b7325 100644
--- a/internal/gnmiserver/model.go
+++ b/internal/gnmiserver/model.go
@@ -35,17 +35,19 @@ type GoStructEnumData map[string]map[int64]ygot.EnumDefinition
 type Model struct {
 	modelData       []*pb.ModelData
 	structRootType  reflect.Type
+	schemaTree      map[string]*yang.Entry
 	schemaTreeRoot  *yang.Entry
-	jsonUnmarshaler JSONUnmarshaler
+	jsonUnmarshaler ytypes.UnmarshalFunc
 	enumData        GoStructEnumData
 }
 
 // NewModel returns an instance of Model struct.
-func NewModel(m []*pb.ModelData, t reflect.Type, r *yang.Entry, f JSONUnmarshaler, e GoStructEnumData) *Model {
+func NewModel(m []*pb.ModelData, t reflect.Type, st *ytypes.Schema, f ytypes.UnmarshalFunc, e GoStructEnumData) *Model {
 	return &Model{
 		modelData:       m,
 		structRootType:  t,
-		schemaTreeRoot:  r,
+		schemaTree:      st.SchemaTree,
+		schemaTreeRoot:  st.RootSchema(),
 		jsonUnmarshaler: f,
 		enumData:        e,
 	}
diff --git a/internal/gnmiserver/server.go b/internal/gnmiserver/server.go
index 423265267e4ae83e160ceeb30ea4fd48dd6a05d1..7c618132fb13ea4276e9388f363d7e187a3d5c3d 100644
--- a/internal/gnmiserver/server.go
+++ b/internal/gnmiserver/server.go
@@ -23,7 +23,6 @@ import (
 	"fmt"
 	"io"
 	"reflect"
-	"strconv"
 	"time"
 
 	"golang.org/x/net/context"
@@ -204,213 +203,6 @@ func (s *Server) checkEncodingAndModel(encoding pb.Encoding, models []*pb.ModelD
 	return nil
 }
 
-// doDelete deletes the path from the json tree if the path exists. If success,
-// it calls the callback function to apply the change to the device hardware.
-func (s *Server) doDelete(jsonTree map[string]interface{}, prefix, path *pb.Path) (*pb.UpdateResult, error) {
-	// Update json tree of the device config
-	var curNode interface{} = jsonTree
-	pathDeleted := false
-	fullPath := gnmiFullPath(prefix, path)
-	schema := s.model.schemaTreeRoot
-	for i, elem := range fullPath.Elem { // Delete sub-tree or leaf node.
-		node, ok := curNode.(map[string]interface{})
-		if !ok {
-			break
-		}
-
-		// Delete node
-		if i == len(fullPath.Elem)-1 {
-			if elem.GetKey() == nil {
-				delete(node, elem.Name)
-				pathDeleted = true
-				break
-			}
-			pathDeleted = deleteKeyedListEntry(node, elem)
-			break
-		}
-
-		if curNode, schema = getChildNode(node, schema, elem, false); curNode == nil {
-			break
-		}
-	}
-	if reflect.DeepEqual(fullPath, pbRootPath) { // Delete root
-		for k := range jsonTree {
-			delete(jsonTree, k)
-		}
-	}
-
-	//// Apply the validated operation to the config tree and device.
-	if pathDeleted {
-		//	newConfig, err := s.toGoStruct(jsonTree)
-		//	if err != nil {
-		//		return nil, status.Error(codes.Internal, err.Error())
-		//	}
-		//	if s.callback != nil {
-		//		if applyErr := s.callback(newConfig); applyErr != nil {
-		//			if rollbackErr := s.callback(s.config); rollbackErr != nil {
-		//				return nil, status.Errorf(codes.Internal, "error in rollback the failed operation (%v): %v", applyErr, rollbackErr)
-		//			}
-		//			return nil, status.Errorf(codes.Aborted, "error in applying operation to device: %v", applyErr)
-		//		}
-		//	}
-	}
-	return &pb.UpdateResult{
-		Path: path,
-		Op:   pb.UpdateResult_DELETE,
-	}, nil
-}
-
-// doReplaceOrUpdate validates the replace or update operation to be applied to
-// the device, modifies the json tree of the config struct, then calls the
-// callback function to apply the operation to the device hardware.
-func (s *Server) doReplaceOrUpdate(jsonTree map[string]interface{}, op pb.UpdateResult_Operation, prefix, path *pb.Path, val *pb.TypedValue) (*pb.UpdateResult, error) {
-	// Validate the operation.
-	fullPath := gnmiFullPath(prefix, path)
-	emptyNode, entry, err := ytypes.GetOrCreateNode(s.model.schemaTreeRoot, s.model.newRootValue(), fullPath)
-	if err != nil {
-		return nil, status.Errorf(codes.NotFound, "path %v is not found in the config structure: %v", fullPath, err)
-	}
-
-	if entry.ReadOnly() {
-		return nil, status.Errorf(codes.Internal, "It is not possible to change the value of a config false field at path: %s", entry.Path())
-	}
-
-	jsonIETFValue := val.GetJsonIetfVal()
-	var nodeVal interface{}
-	nodeStruct, ok := emptyNode.(ygot.ValidatedGoStruct)
-	if ok {
-		if err := s.model.jsonUnmarshaler(jsonIETFValue, nodeStruct); err != nil {
-			return nil, status.Errorf(codes.InvalidArgument, "unmarshaling json data to config struct fails: %v", err)
-		}
-		if err := nodeStruct.Validate(); err != nil {
-			return nil, status.Errorf(codes.InvalidArgument, "config data validation fails: %v", err)
-		}
-		var err error
-		if nodeVal, err = ygot.ConstructIETFJSON(nodeStruct, &ygot.RFC7951JSONConfig{}); err != nil {
-			msg := fmt.Sprintf("error in constructing IETF JSON tree from config struct: %v", err)
-			log.Error(msg)
-			return nil, status.Error(codes.Internal, msg)
-		}
-	} else {
-		var err error
-		if nodeVal, err = value.ToScalar(val); err != nil {
-			return nil, status.Errorf(codes.Internal, "cannot convert leaf node to scalar type: %v", err)
-		}
-	}
-
-	// Check if val contains config false fields and return an error if thats
-	// the case.
-	if nodeStruct != nil {
-		nodeStructCopy, err := ygot.DeepCopy(nodeStruct)
-		if err != nil {
-			return nil, status.Errorf(codes.Internal, "could not create a deep copy of current nodeStruct: %v", err)
-		}
-
-		if err := ygot.PruneConfigFalse(entry, nodeStruct); err != nil {
-			return nil, status.Errorf(codes.Internal, "failed prune config false for nodeStruct: %v", err)
-		}
-
-		diff, err := ygot.Diff(nodeStructCopy, nodeStruct)
-		if err != nil {
-			return nil, status.Errorf(codes.Internal, "failed to create a diff for nodeStruct: %v", err)
-		}
-
-		if diff != nil && len(diff.Delete) != 0 {
-			paths := make([]string, 0)
-			for _, path := range diff.Delete {
-				p, err := ygot.PathToString(path)
-				if err != nil {
-					return nil, status.Errorf(codes.Internal, "failed to create string from path: %v", err)
-				}
-				paths = append(paths, p)
-			}
-			return nil, status.Errorf(codes.InvalidArgument, "Can not set config false paths: %v", paths)
-		}
-	} else if entry.ReadOnly() {
-		return nil, status.Errorf(codes.Internal, "It is not possible to change the value of a config false field at path: %s", entry.Path())
-	}
-
-	// Update json tree of the device config.
-	var curNode interface{} = jsonTree
-	schema := s.model.schemaTreeRoot
-	for i, elem := range fullPath.Elem {
-		switch node := curNode.(type) {
-		case map[string]interface{}:
-			// Set node value.
-			if node != nil {
-				if i == len(fullPath.Elem)-1 {
-					if elem.GetKey() == nil {
-						if grpcStatusError := setPathWithoutAttribute(op, node, elem, nodeVal); grpcStatusError != nil {
-							return nil, grpcStatusError
-						}
-						break
-					}
-					if grpcStatusError := setPathWithAttribute(op, node, elem, nodeVal); grpcStatusError != nil {
-						return nil, grpcStatusError
-					}
-					break
-				}
-
-				logrus.Debug("doReplaceOrUpdate, node: ", node)
-				if curNode, schema = getChildNode(node, schema, elem, true); curNode == nil {
-					return nil, status.Errorf(codes.NotFound, "path elem not found: %v", elem)
-				}
-			} else {
-				logrus.Debugf("node is nil for path elem: %s", elem.String())
-			}
-		case []interface{}:
-			return nil, status.Errorf(codes.NotFound, "incompatible path elem: %v", elem)
-		default:
-			return nil, status.Errorf(codes.Internal, "wrong node type: %T", curNode)
-		}
-	}
-	if reflect.DeepEqual(fullPath, pbRootPath) { // Replace/Update root.
-		if op == pb.UpdateResult_UPDATE {
-			return nil, status.Error(codes.Unimplemented, "update the root of config tree is unsupported")
-		}
-		nodeValAsTree, ok := nodeVal.(map[string]interface{})
-		if !ok {
-			return nil, status.Errorf(codes.InvalidArgument, "expect a tree to replace the root, got a scalar value: %T", nodeVal)
-		}
-		for k := range jsonTree {
-			delete(jsonTree, k)
-		}
-		for k, v := range nodeValAsTree {
-			jsonTree[k] = v
-		}
-	}
-	//newConfig, err := s.toGoStruct(jsonTree)
-	//if err != nil {
-	//	return nil, status.Error(codes.Internal, err.Error())
-	//}
-
-	//// Apply the validated operation to the device.
-	//if s.callback != nil {
-	//	if applyErr := s.callback(newConfig); applyErr != nil {
-	//		if rollbackErr := s.callback(s.config); rollbackErr != nil {
-	//			return nil, status.Errorf(codes.Internal, "error in rollback the failed operation (%v): %v", applyErr, rollbackErr)
-	//		}
-	//		return nil, status.Errorf(codes.Aborted, "error in applying operation to device: %v", applyErr)
-	//	}
-	//}
-	return &pb.UpdateResult{
-		Path: path,
-		Op:   op,
-	}, nil
-}
-
-func (s *Server) toGoStruct(jsonTree map[string]interface{}) (ygot.ValidatedGoStruct, error) {
-	jsonDump, err := json.Marshal(jsonTree)
-	if err != nil {
-		return nil, fmt.Errorf("error in marshaling IETF JSON tree to bytes: %v", err)
-	}
-	goStruct, err := s.model.NewConfigStruct(jsonDump)
-	if err != nil {
-		return nil, fmt.Errorf("error in creating config struct from IETF JSON data: %v", err)
-	}
-	return goStruct, nil
-}
-
 // getGNMIServiceVersion returns a pointer to the gNMI service version string.
 // The method is non-trivial because of the way it is defined in the proto file.
 func getGNMIServiceVersion() (*string, error) {
@@ -432,51 +224,6 @@ func getGNMIServiceVersion() (*string, error) {
 	return ver.(*string), nil
 }
 
-// deleteKeyedListEntry deletes the keyed list entry from node that matches the
-// path elem. If the entry is the only one in keyed list, deletes the entire
-// list. If the entry is found and deleted, the function returns true. If it is
-// not found, the function returns false.
-func deleteKeyedListEntry(node map[string]interface{}, elem *pb.PathElem) bool {
-	curNode, ok := node[elem.Name]
-	if !ok {
-		return false
-	}
-
-	keyedList, ok := curNode.([]interface{})
-	if !ok {
-		return false
-	}
-	for i, n := range keyedList {
-		m, ok := n.(map[string]interface{})
-		if !ok {
-			log.Errorf("expect map[string]interface{} for a keyed list entry, got %T", n)
-			return false
-		}
-		keyMatching := true
-		for k, v := range elem.Key {
-			attrVal, ok := m[k]
-			if !ok {
-				return false
-			}
-			if v != fmt.Sprintf("%v", attrVal) {
-				keyMatching = false
-				break
-			}
-		}
-		if keyMatching {
-			listLen := len(keyedList)
-			if listLen == 1 {
-				delete(node, elem.Name)
-				return true
-			}
-			keyedList[i] = keyedList[listLen-1]
-			node[elem.Name] = keyedList[0 : listLen-1]
-			return true
-		}
-	}
-	return false
-}
-
 // gnmiFullPath builds the full path from the prefix and path.
 func gnmiFullPath(prefix, path *pb.Path) *pb.Path {
 	fullPath := &pb.Path{Origin: path.Origin}
@@ -489,73 +236,6 @@ func gnmiFullPath(prefix, path *pb.Path) *pb.Path {
 	return fullPath
 }
 
-// isNIl checks if an interface is nil or its value is nil.
-func isNil(i interface{}) bool {
-	if i == nil {
-		return true
-	}
-	switch kind := reflect.ValueOf(i).Kind(); kind {
-	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
-		return reflect.ValueOf(i).IsNil()
-	default:
-		return false
-	}
-}
-
-// setPathWithAttribute replaces or updates a child node of curNode in the IETF
-// JSON config tree, where the child node is indexed by pathElem with attribute.
-// The function returns grpc status error if unsuccessful.
-func setPathWithAttribute(op pb.UpdateResult_Operation, curNode map[string]interface{}, pathElem *pb.PathElem, nodeVal interface{}) error {
-	nodeValAsTree, ok := nodeVal.(map[string]interface{})
-	if !ok {
-		return status.Errorf(codes.InvalidArgument, "expect nodeVal is a json node of map[string]interface{}, received %T", nodeVal)
-	}
-	m := getKeyedListEntry(curNode, pathElem, true)
-	if m == nil {
-		return status.Errorf(codes.NotFound, "path elem not found: %v", pathElem)
-	}
-	if op == pb.UpdateResult_REPLACE {
-		for k := range m {
-			delete(m, k)
-		}
-	}
-	for attrKey, attrVal := range pathElem.GetKey() {
-		m[attrKey] = attrVal
-		if asNum, err := strconv.ParseFloat(attrVal, 64); err == nil {
-			m[attrKey] = asNum
-		}
-		for k, v := range nodeValAsTree {
-			if k == attrKey && fmt.Sprintf("%v", v) != attrVal {
-				return status.Errorf(codes.InvalidArgument, "invalid config data: %v is a path attribute", k)
-			}
-		}
-	}
-	for k, v := range nodeValAsTree {
-		m[k] = v
-	}
-	return nil
-}
-
-// setPathWithoutAttribute replaces or updates a child node of curNode in the
-// IETF config tree, where the child node is indexed by pathElem without
-// attribute. The function returns grpc status error if unsuccessful.
-func setPathWithoutAttribute(op pb.UpdateResult_Operation, curNode map[string]interface{}, pathElem *pb.PathElem, nodeVal interface{}) error {
-	target, hasElem := curNode[pathElem.Name]
-	nodeValAsTree, nodeValIsTree := nodeVal.(map[string]interface{})
-	if op == pb.UpdateResult_REPLACE || !hasElem || !nodeValIsTree {
-		curNode[pathElem.Name] = nodeVal
-		return nil
-	}
-	targetAsTree, ok := target.(map[string]interface{})
-	if !ok {
-		return status.Errorf(codes.Internal, "error in setting path: expect map[string]interface{} to update, got %T", target)
-	}
-	for k, v := range nodeValAsTree {
-		targetAsTree[k] = v
-	}
-	return nil
-}
-
 // Capabilities returns supported encodings and supported models.
 func (s *Server) Capabilities(ctx context.Context, req *pb.CapabilityRequest) (*pb.CapabilityResponse, error) {
 	ver, err := getGNMIServiceVersion()
@@ -691,52 +371,38 @@ func (s *Server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse,
 	s.config.Lock()
 	defer s.config.Unlock()
 
-	logrus.Debug("Current data: ", s.config.Data)
-	// Obtain current configuration as JSON
-	jsonTree, err := ygot.ConstructIETFJSON(s.config.Data, &ygot.RFC7951JSONConfig{})
-	if err != nil {
-		msg := fmt.Sprintf("error in constructing IETF JSON tree from config struct: %v", err)
-		log.Error(msg)
-		return nil, status.Error(codes.Internal, msg)
-	}
+	logrus.Debug("Incoming Set Request: ", req)
 
-	prefix := req.GetPrefix()
 	var results []*pb.UpdateResult
 
-	for _, path := range req.GetDelete() {
-		res, grpcStatusError := s.doDelete(jsonTree, prefix, path)
-		if grpcStatusError != nil {
-			return nil, grpcStatusError
-		}
-		results = append(results, res)
-	}
-	for _, upd := range req.GetReplace() {
-		res, grpcStatusError := s.doReplaceOrUpdate(jsonTree, pb.UpdateResult_REPLACE, prefix, upd.GetPath(), upd.GetVal())
-		if grpcStatusError != nil {
-			return nil, grpcStatusError
-		}
-		results = append(results, res)
+	newConfig, err := ygot.DeepCopy(s.config.Data)
+	if err != nil {
+		return nil, status.Error(codes.Internal, err.Error())
 	}
-	for _, upd := range req.GetUpdate() {
-		res, grpcStatusError := s.doReplaceOrUpdate(jsonTree, pb.UpdateResult_UPDATE, prefix, upd.GetPath(), upd.GetVal())
-		if grpcStatusError != nil {
-			return nil, grpcStatusError
-		}
-		results = append(results, res)
+
+	newSchema := &ytypes.Schema{
+		Root:       newConfig,
+		SchemaTree: s.model.schemaTree,
+		Unmarshal:  s.model.jsonUnmarshaler,
 	}
 
-	newConfig, err := s.toGoStruct(jsonTree)
+	err = ytypes.UnmarshalSetRequest(newSchema, req)
 	if err != nil {
 		return nil, status.Error(codes.Internal, err.Error())
 	}
 
+	valNewConfig, ok := newConfig.(ygot.ValidatedGoStruct)
+	if !ok {
+		return nil, status.Error(codes.Internal, fmt.Sprintf("wrong type for new config, expected: %T; got: %T", (ygot.ValidatedGoStruct)(nil), newConfig))
+	}
+
 	currentConfig, err := ygot.DeepCopy(s.config.Data)
 	if err != nil {
 		return nil, status.Error(codes.Internal, err.Error())
 	}
 
 	// Apply the validated operations to the device.
-	diff, applyErr := s.callback(newConfig, currentConfig.(ygot.ValidatedGoStruct))
+	diff, applyErr := s.callback(valNewConfig, currentConfig.(ygot.ValidatedGoStruct))
 	if applyErr != nil {
 		if _, rollbackErr := s.callback(currentConfig.(ygot.ValidatedGoStruct), s.config.Data); rollbackErr != nil {
 			return nil, status.Errorf(codes.Internal, "error in rollback the failed operation (%v): %v", applyErr, rollbackErr)
@@ -744,7 +410,7 @@ func (s *Server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse,
 		return nil, status.Errorf(codes.Aborted, "error in applying operation to device: %v", applyErr)
 	}
 
-	s.config.Data = newConfig
+	s.config.Data = valNewConfig
 
 	// notify subscribers about the changes
 	err = s.PublishNotificationsToSubscribers(diff)
diff --git a/target.go b/target.go
index 02230ecb6bf697abe9145ad9c476f635e317180a..67067c7980b79cb10df49da34e68751821c57a58 100644
--- a/target.go
+++ b/target.go
@@ -63,7 +63,7 @@ func (gt *GnmiTarget) Start(bindAddress string, certFile string, keyFile string,
 	gnmiModel := server.NewModel(gt.modeldata,
 		// NOTE: could be problematic
 		reflect.TypeOf(gt.model),
-		gt.schema.RootSchema(),
+		gt.schema,
 		gt.unmarshalFn,
 		gt.ΛEnum)